且构网

分享程序员开发的那些事...
且构网 - 分享程序员编程开发的那些事

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

更新时间:2022-12-30 10:27:47

问题是 arrange()函数期望您的参数为符号
但是,您的输入$ top3 是一个字符串。



诀窍是:

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

你可以使用?替代来看看它是如何工作的。



短版本解析表达式:

  employeestats%>%arrange(desc(col))

转换成由调用的(功能)和名称组成的解析树>(符号,常量,对象),允许我们替换组件形成一个新的表达式。



为此,表达式不被评估(意思是, 雇佣者不是安排 d)。



这里 col 并不意味着什么。它只是作为占位符。
通过将列表(col = as.symbol(input $ top3))替换为替换,我们将虚拟符号 col 替换为我们要安排的实际符号, as.symbol(input $ top3)
根据当前输入,这将是 TotalAwarded NumberOfAwards (符号,而不是字符串)



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


I'm writing a new Shiny app, and I would like to stay within the Hadleyverse by using dplyr commands for data manipulation. I want Shiny to print a table showing only the top 3 observations according to a variable that can be chosen by the user. For example, one user may want to see the top 3 employees in terms of number of awards received, while another will want to see the top 3 in terms of number of award points earned.

In my latest attempt, I have this for 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")
)))

and this for 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)
})

Outside of Shiny, the command

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

gives the answer that I want for the top 3 award winners. In Shiny, the full table and the selection box are printed without the Top 3 table, and I get the message "Error in eval(substitute(expr), envir, enclos) : cannot arrange column of class 'NULL'". I know that this has something to do with both Shiny and dplyr using nonstandard functions, and that it could make a difference if R sees NumberOfAwards or the character string "NumberOfAwards". I've tried things like deparse(substitute()), using numbers to indicate the columns to arrange by, etc. without success. This doesn't have to be elaborate; for example, I don't care about ties for 3rd place.

Any ideas? Thanks for the help.

The problem is that arrange() function expects your argument as a symbol. However, your input$top3 is a string.

The trick is:

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)

You can use ?substitute to see how it works.

Short version, it parse the expression:

employeestats %>% arrange(desc(col))

into a parse tree consisting of call's (functions) and name's (symbols, constants, objects), allowing us to substitute the components to form a new expression.

To this point, the expression is not evaluated (meaning, the employeestats is not arranged yet).

Here col doesn't really mean anything. It simply serves as a placeholder. And by passing list(col=as.symbol(input$top3)) to substitute, we replace the dummy symbol col by the actual symbol we would like to arrange by, as.symbol(input$top3). Depending on the current input, this would either be TotalAwarded or NumberOfAwards (symbols, not strings anymore).

Finally, the eval() function evaluated the expression (with col replaced by the actual symbol), and returns the sorted data.frame.