【问题标题】:Shiny: how to control width of rownames() in renderTable?Shiny:如何控制 renderTable 中 rownames() 的宽度?
【发布时间】:2016-12-23 19:33:57
【问题描述】:

下面的代码生成一个包含 3 行和 3 列的输入表(为了简化情况 - 见下图)。根据输入,我需要在输入表下方生成 9 个直方图,重要的是直方图应与输入框垂直对齐。目前情况并非如此。

我正在考虑的一个选项是在包含绘图之前使用偏移量 1。为了确保绘图对齐,输入的行名(alt1、alt2、a3)应该以这样的方式出现,即它们恰好占据 1 列以匹配偏移量。默认情况下,renderTable 似乎使用了自动调整。我在网上搜索过,但找不到控制行名宽度的方法。

有人可以帮忙吗?任何输入将不胜感激。非常感谢。

library(shiny)
library(grid)
library(gridBase)

u <- shinyUI(navbarPage(
"My Application",
tabPanel("Component 1",
       fluidPage(

         fluidRow(column(6,
          tableOutput('decision_Matrix'),offset=0)       
         ),
         fluidRow(column(5,
           plotOutput('decision_Matrix_plots')
           ,offset=1)       
         )
       )),
tabPanel("Component 2")
))

s <- shinyServer(

function(input,output) {

  output$decision_Matrix <- renderTable({

        matrix_input <- matrix(data = NA,nrow = 3,ncol = 3)
  for (j in 1:3) {
    for (i in 1:3) {
      matrix_input[i,j] <- paste0("<input id='C",j,"_A",i,"' type='number' class='form-control shiny-bound-input'  value='",input[[paste0("C",j,"_A",i)]],"'>")
    }
  }

  rownames(matrix_input) <- c("alt1","alt2","a3")

  colnames(matrix_input) <- c("crit1","crit2","t3")

  matrix_input
},include.rownames = TRUE,sanitize.text.function = function(x) x)

output$decision_Matrix_plots <- renderPlot({    

  layout(matrix(c(1,2,3,4,5,6,7,8,9),nrow = 3,ncol = 3))
  for (j in 1:3) {
    for (i in 1:3) {
      set.seed(123)
      n <- input[[paste0("C",j,"_A",i)]]
      if (is.null(n) || is.na(n) || n < 1) n <- 1
      hist(rnorm(n),breaks = 10,main=sprintf("histogram of rnorm( %d )",n))
    }
  }
  recordPlot()
})

})
shinyApp(ui = u,server = s)

【问题讨论】:

    标签: r shiny


    【解决方案1】:

    就像你说的那样,rownames 搞乱了你的对齐方式。使用fluidRow 和列Shiny 正在使用Bootstrap。有关流体行和列的基本原理,请查看http://www.w3schools.com/bootstrap/bootstrap_grid_basic.asp

    垂直对齐的解决方案是将行名放在单独的列中。以下更改修复了垂直对齐。

        ...
                         fluidRow(column(1,
                                         tableOutput('m_rownames'),offset=0, align="left"),
                                 column(5,
                                    tableOutput('decision_Matrix'),offset=0, align="right")
                         ),
                         fluidRow(column(5,
                                         plotOutput('decision_Matrix_plots')
                                         ,offset=1, align="right")
                         )
        ....
    
                },include.rownames = FALSE,sanitize.text.function = function(x) x)
                output$m_rownames <- renderTable({ c("alt1","alt2","a3") })
    

    这会将您的行名放在宽度为 1 的单独列中,并且您的矩阵和绘图分别放在 5 个相应的列中。但是,这会打乱行名和矩阵的水平对齐方式。稍后我可能会有一点时间来看看这个,但现在我会留给你来调整它。

    这是结果

    【讨论】:

    • 感谢 Etienne,实际上我也有同样的想法,但 m_rownames 中的行高与表中的行高不同,因为它包含数字输入。我找到了以下手动修复此问题的方法:“tags$head(tags$style(type="text/css", "#m_rownames table td {line-height:245%;}"))”。 245% 是通过反复试验找到的。然而,这并不令人满意。这是一个简化的例子:在我的表格中,我还有一些单选按钮,它们占据了更多的垂直空间。我认为行名不应该在不同的表中。如果你找到smth,请告诉我。我也在做这个。 H
    • 在不同列中水平对齐项目非常困难,因为列中项目的位置由浏览器决定,并且取决于浏览器窗口的大小(和其他因素)。你可以尝试fixedPage 来摆脱这种依赖。另一种选择是你所做的。在这种情况下,浏览器会确定行内项目的位置,因此存在相同问题的 2 个版本。我认为没有解决方案,但如果有,您可能会在 HTML 或 CSS 论坛上找到它。
    【解决方案2】:

    就对齐而言,最好的选择是制作 3 列。每个包含 3 个输入和 3 个相应的输出。第一列显示其他人没有的行名。这需要进行一些重组,而且它并不完美,因为第一列将与其他列不同。这里有一些代码

        ...
        fluidRow(
               column(4,
                     tableOutput('decision_MatrixC1'),offset=0),
               column(4,
                     tableOutput('decision_MatrixC2'),offset=0),
               column(4,
                     tableOutput('decision_MatrixC3'),offset=0)
        ),
        fluidRow(
               column(3,
                     plotOutput('decision_Matrix_plotsC1')
                                         ,offset=1),
               column(4,
                     plotOutput('decision_Matrix_plotsC2')
                                        ,offset=0),
               column(4,
                     plotOutput('decision_Matrix_plotsC3')
                                       ,offset=0)
         )
         ....
         output$decision_MatrixC1 <- renderTable({                        
                 matrix_input <- matrix(data = NA,nrow = 3,ncol = 1)
                 for (j in 1:1) {
                        for (i in 1:3) {
                                  matrix_input[i,j] <- paste0("<input id='C",j,"_A",i,"' type='number' class='form-control shiny-bound-input'  value='",input[[paste0("C",j,"_A",i)]],"'>")
                         }}                        
                 rownames(matrix_input) <- c("alt1","alt2","a3")                        
                 colnames(matrix_input) <- c("crit1")
    
                 matrix_input
                },include.rownames = TRUE,sanitize.text.function = function(x) x)
    
                output$decision_MatrixC2 <- renderTable({
                        matrix_input <- matrix(data = NA,nrow = 3,ncol = 1)
                        for (j in 1:1) {
                                for (i in 1:3) {
                                        matrix_input[i,j] <- paste0("<input id='C",j+1,"_A",i,"' type='number' class='form-control shiny-bound-input'  value='",input[[paste0("C",j+1,"_A",i)]],"'>")
                                }}                        
                        rownames(matrix_input) <- c("alt1","alt2","a3")
                        colnames(matrix_input) <- c("crit2")
                        matrix_input
                },include.rownames = FALSE,sanitize.text.function = function(x) x)
    

    第三列的情节几乎相同。显然这段代码需要一些清理,但我想让它尽可能接近你的代码。您可以以类似的方式将其组织成行,而不是像这样在列中组织它。结果是

    【讨论】:

      猜你喜欢
      • 2017-10-28
      • 1970-01-01
      • 2015-11-15
      • 1970-01-01
      • 2023-03-24
      • 2021-08-04
      • 2021-02-11
      • 2017-02-03
      • 1970-01-01
      相关资源
      最近更新 更多