我正在编写一个新的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()),使用数字来表示要排列的列等等,但没有成功。这不必详细说明;例如,我不关心第三名的关系。
有什么想法吗?谢谢你的帮助。
答案 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)
。
根据当前输入,这可能是TotalAwarded
或NumberOfAwards
(符号,而不是字符串)。
最后,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)