来自 renderDataTable 的响应式输入

Posted

技术标签:

【中文标题】来自 renderDataTable 的响应式输入【英文标题】:Reactive input from renderDataTable 【发布时间】:2014-03-04 03:43:15 【问题描述】:

更新(2015 年 12 月 18 日) 解决这个问题的最佳方法在这里:Get Selected Row From DataTable in Shiny App

=======================

我正在尝试使用用户提供的行选择反应性地重新显示数据集。作为一个玩具示例,

ui.R

library(shiny)

shinyUI(pageWithSidebar(
  headerPanel('Examples of DataTables'),
  sidebarPanel(
    checkboxGroupInput('show_vars', 'Columns to show:', names(mtcars),
                       selected = names(mtcars))
  ),
  mainPanel(
               dataTableOutput("mytable")
    )
  )
)

server.R

library(shiny)

shinyServer(function(input, output) 

  # sorted columns are colored now because CSS are attached to them
  output$mytable = renderDataTable(
    addRadioButtons <- paste0('<input type="radio" name="row', 1:nrow(mtcars), '" value="', 1:nrow(mtcars), '">',"")
    #Display table with radio buttons
    cbind(Pick=addRadioButtons, mtcars[, input$show_vars, drop=FALSE])
  , options = list(bSortClasses = TRUE, aLengthMenu = c(5, 25, 50), iDisplayLength = 25))

)

我想使用单选按钮从用户那里收集行号(比如上图中的第 4 行),使用一些反应式表达,比如rowSelect(),然后在一些操作之后动态重新显示表格例如,数据集

 mtcars[mtcars[,1] > mtcars[rowSelect(),1], input$show_vars, drop=FALSE]

每次用户选择一行时都会动态删除某些行。

更新(2014 年 2 月 7 日)

结合@Julien 建议的更改并实现@Vincent 建议的方法,server.R 变为:

library(shiny)

shinyServer(function(input, output) 

  #reactive row-selection 
  rowSelect <- reactive(
  if(is.null(input[["row"]])) 1 #initialize
  else as.numeric(input[["row"]]))

  # User-selected sorting of dataset
  output$mytable = renderDataTable(
    addRadioButtons <- paste0('<input type="radio" name="row" value="', 1:nrow(mtcars), '">')
    cbind(Pick=addRadioButtons, mtcars[order(mtcars[,1] - rnorm(nrow(mtcars), mtcars[rowSelect(),1])), input$show_vars, drop=FALSE])
  , options = list(bSortClasses = TRUE, aLengthMenu = c(5, 10, 20), iDisplayLength = 10))
)

正如@agstudy 所猜测的,保持数据表中的行数与以前相同(不是子集)很重要,因此order(mtcars[,1] - rnorm(nrow(mtcars), mtcars[rowSelect(),1])) 上面的奇怪排序操作。

更新 2(2014 年 2 月 7 日)

无论如何,这个练习确实揭示了我的示例中的一个缺陷。 我最初的意图是使用单独的协方差/相似度矩阵来根据用户选择的行获取显示数据表的排序顺序.由于矩阵和表格将非常大,因此将它们作为下拉输入列表或任何其他单选按钮输入方法包含在侧面板中是没有意义的。在显示整个数据表后,它必须来自用户选择。

要实现这一点,只需将单选按钮中的 value 替换为唯一的行 ID。在server.R中,使用rowSelect()表达式(data是相似度矩阵,meta是显示的数据表,IDdatameta共享的唯一行标识符):

addRadioButtons <- paste0('<input type="radio" name="row" value=', meta[order(data[rowSelect(),]),"ID"], '>')

cbind(Pick=addRadioButtons, meta[order(data[rowSelect(),]),input$show_vars])

这将继续根据用户选择的行重新排序数据表,同时通过唯一的行 ID 根据相似度矩阵选择顺序。希望这对某人有所帮助。

但是,如果我使用 rowSelect 反应式表达式,那么基于排序数据表的行选择不会给我正确的相似矩阵行选择(数据集的顺序会改变但不适用于矩阵 - 递归问题)。这意味着我需要收集除行号的无线电输入以外的其他内容——更像是一个识别行 ID(它与表——其中一个列——和矩阵都匹配),使用表单或点击提交——大致如下:Selecting all text in html text input when clicked

感谢您的帮助。 @Vincent,您的应用程序非常酷。希望最终能到达那里。我会接受你的回答。

【问题讨论】:

你不能用闪亮的方式做到这一点。这是一种动态输入。我认为这里的解决方案是嵌入一些jquery。例如,请参阅this。 为什么你不能在 Shiny 中做到这一点? input$row1 等具有您可以访问并用于子集数据的值。这是否是实现该目标的好方法是另一个问题。 没有。它不是 input$row1 ,它是 input$row_i ,其中“i”是未知的(你应该本地循环来获取它)。 这是一个细节,但单选按钮应该具有所有相同的名称,因为当用户单击单选按钮时,它会变为选中状态,而所有其他具有相同名称的单选按钮将变为未选中状态。如果你想要几个选择,你需要的不是收音机而是复选框,(它们也应该有相同的names)。 【参考方案1】:

不是一个答案,而是一个冗长的评论:我认为你可以这样做,但它会变得有点混乱。一旦有人选择了一个单选按钮并显示了数据的子集,您如何返回显示所有数据?这仅适用于第一列吗?当数据的行数较少时,您是否要重新创建所有单选按钮? renderDataTable 将(在某些时候)可以选择在每列下方的框中包含类似“> 20”的内容。同时,您最好尝试使用 textInput 对数据进行子集化。例如,请参阅 app 中的数据 > 查看。如果这不是您想要的,请告诉我(我们)您想要实现的目标。

【讨论】:

我看不出您的示例与操作请求之间有任何关系。 OP 似乎想根据 mpg 值对数据进行子集化。在 data > view 中有一个 textInput 允许您输入类似 mpg > 20 的内容(或应用程序中的钻石数据价格 > 5000)。如果我对 OP 的意图有误,我可以删除参考。 这里的主要问题是如何检测选择了哪些单选按钮(这是一个 gui 问题而不是数据问题),您对所选行所做的只是一个用例或一个示例。这就是我阅读问题的方式,但我可能是错的。 添加 observe( for(i in 1:nrow(mtcars)) print(input[[paste0("row",i)]]) ) 到 server.R 将显示哪些单选按钮在 R 终端中选择。让我们拭目以待,看看 OP 在寻找什么 :) 感谢 cmets。对不起,已经走出了一点。 @agstudy 是正确的,一旦行被识别,操作只是一个例子。我会试试observe 并尽快回来。

以上是关于来自 renderDataTable 的响应式输入的主要内容,如果未能解决你的问题,请参考以下文章

使输入文本响应式

浅析响应式网页设计

响应式文件管理器回调函数输入字段文本

css 使用iFrame的响应式YouTube和Vimeo视频 - 来自https://www.ostraining.com/blog/coding/responsive-videos/

TW洞见|也谈响应式编程

输入搜索字段在响应式网站的移动版本上无法正常工作