将用户规范作为参数传递给Shiny中的dplyr

时间:2014-08-08 20:42:01

标签: r shiny dplyr

我正在编写一个新的Shiny应用程序,我想通过使用dplyr命令进行数据操作来保持在Hadleyverse中。我希望Shiny打印一个表格,根据用户可以选择的变量仅显示前3个观察结果。例如,一个用户可能希望在收到的奖励数量方面看到前三名员工,而另一个用户希望在获得的奖励积分数量方面看到前三名。

在我最近的尝试中,我为ui.R做了这个:

library(shiny)
shinyUI(fluidPage(
verticalLayout(
tableOutput("tbl"),
selectInput("top3", label = h4("Quantity"), 
  choices = list("Number of awards" = "NumberOfAwards", 
  "Total points awarded" = "TotalAwarded")), 
tableOutput("t3")
)))

这对于server.R:

library(dplyr)
library(shiny)
shinyServer(function(input, output) {
employeestats <- read.table(header=TRUE, text='
Employee  NumberOfAwards TotalAwarded
Al        3              10
Betty     6              20
Chuck     2              5
Donna     4              15
Ed        0              0
')  
output$tbl <- renderTable({ 
employeestats
},include.rownames=TRUE) 
datasetInput <- reactive({employeestats})
output$t3 <- renderTable({ 
head(datasetInput() %>% arrange(desc(input$top3)),n=3)  
},include.rownames=TRUE)
})

在Shiny之外,命令

head(employeestats %>% arrange(desc(NumberOfAwards)),n=3)

给出了前三名获奖者的答案。在Shiny中,完整的表格和选择框打印时没有Top 3表格,我收到消息&#34; eval中的错误(替换(expr),envir,enclos):无法安排类的列&#39; NULL&#39;&#34 ;.我知道这与使用非标准函数的Shiny和dplyr有关,如果R看到NumberOfAwards或字符串&#34; NumberOfAwards&#34;它可能会有所不同。我尝试过像deparse(substitute()),使用数字来表示要排列的列等等,但没有成功。这不必详细说明;例如,我不关心第三名的关系。

有什么想法吗?谢谢你的帮助。

2 个答案:

答案 0 :(得分:6)

问题是arrange()函数希望你的参数为symbol。 但是,您的input$top3是一个字符串。

诀窍是:

output$t3 <- renderTable({ 
    sorted_stats <- eval(substitute(employeestats %>% arrange(desc(col)), 
                         list(col=as.symbol(input$top3))))
    head(sorted_stats,n=3)  
  },include.rownames=TRUE)

您可以使用?substitute查看其工作原理。

简短版本,它解析表达式:

employeestats %>% arrange(desc(col))

到由call的(函数)和name(符号,常量,对象)组成的解析树中,允许我们用组件替换以形成新的表达式。

到目前为止,还没有评估表达式(意思是employeestats还不是arrange)。

这里col并不意味着什么。它只是一个占位符。 通过将list(col=as.symbol(input$top3))传递给substitute,我们将虚拟符号col替换为我们希望排列的实际符号as.symbol(input$top3)。 根据当前输入,这可能是TotalAwardedNumberOfAwards(符号,而不是字符串)。

最后,eval()函数评估了表达式(col替换为实际符号),并返回已排序的data.frame

答案 1 :(得分:5)

您可能还想查看arrange_(请参阅vignette)。在Shiny应用程序中非常适合。

第一个选项可以满足您的需求。第二个更清洁但不完全是你想要的。我猜第三个选项是理想的,但desc_不是一个函数。可能是一个很好的补充:)

input <- list()
input$top3 <- "mpg"

mtcars %>%
  arrange_(paste0("desc(",input$top3,")"))  %>%
  head(n=3)

mtcars %>%
  arrange_(input$top3)  %>%
  tail(n=3)

# desc_ is not a function (yet)
mtcars %>%
  arrange(desc_(input$top3)) %>%
  head(n=3)