【问题标题】:Using dynamic filters to aggregate data in R Shiny使用动态过滤器在 R Shiny 中聚合数据
【发布时间】:2019-10-31 06:25:42
【问题描述】:

我有这种格式的数据:

Category Subcategory   User   Count1    Count2
  A           a        New     3000      2000
  A           a        Old      300       200
  A           b        New     4000      3000
  A           b        Old      400       300
  B           c        New     4000      3000
  B           c        Old      600       400

我已经为 Category、Subcategory 和 User 编写了 3 个过滤器,并以这种方式输出数据表:

    selectInput('cat', 'Category', choices = c('All', category)),
    selectInput('sub', 'Subcategory', choices = c('All', subcategory)),
    selectInput('user', 'User', c('All', 'New', 'Old')),
    DT::dataTableOutput('table')

choices 参数中的category 和subcategory 是列表。我可以通过用户输入以这种方式过滤数据:

output$table <- DT::renderDataTable({
    if(input$cat == 'All'){data <- data}
    else{data <- data[data$Category == input$cat, ]}
    if(input$user == 'All'){data <- data}
    else{data <- data[data$User== input$user, ]}
    if(input$sub == 'All'){data <- data}
    else{data<- data[data$Subcategory == input$sub, ]}
})

我遇到的问题是,当用户输入“全部”参数时,我需要聚合 count 列。例如,如果用户为子类别和用户输入“全部”,为类别输入“A”,则输出数据表应如下所示:

Category Subcategory   User   Count1    Count2
  A           All      All     7700      5500

或

Category  Count1    Count2
  A        7700      5500

我可以为此编写 if-else 条件,但在实际数据中有 6-8 个过滤器,我想知道是否有更简单的方法来聚合数据,而无需为所有聚合组合编写 if-else 控件(例如聚合所有类别和子类别的新用户或聚合所有类别、子类别和用户等)。

【问题讨论】:

  • 我想我已经找到了解决方案,确认后会发布。

标签: r shiny dplyr aggregate


【解决方案1】:

你可以在 DT::renderDataTable 中尝试这样的事情:

output$table <- DT::renderDataTable({
idx <- which(c(input$cat, input$user, input$sub) != "All")
myvars <- colnames(data)[1:3][idx]

data %>%
  {`if`(input$cat ==  "All", . , filter(., Category == input$cat))} %>% 
  {`if`(input$user == "All", . , filter(., User == input$user))} %>%
  {`if`(input$sub ==  "All", . , filter(., Subcategory == input$sub))} %>%
  {`if`(length(myvars) == 0, ., group_by_at(., myvars) %>% 
          summarise_at(vars(matches("^Count")), sum))}
})

简短说明:

summarise 是 dplyr 等价于 aggregate。 summarise_at 是 summarise 的一个特例:在第一个参数中,您描述了所有要聚合(或汇总)的变量。我输入了matches("^Count"),这意味着所有以"Count" 开头的变量都应该被汇总。第二个参数是聚合函数sum。

【讨论】:

  • 你能解释一下这里发生了什么吗,我不太熟悉 dplyr...summarise_at(vars(matches("^Count")), sum)
【解决方案2】:

我添加了 " " 作为过滤器的默认值...

    selectInput('cat', 'Category', choices = c('','All', category)),
    selectInput('sub', 'Subcategory', choices = c('','All', subcategory)),
    selectInput('user', 'User', c('','All', 'New', 'Old')),
    DT::dataTableOutput('table')

...并根据 UI 输入更改列值。

output$table <- DT::renderDataTable({
 if(input$cat == '' | input$sub == '' | input$user == ''){return(NULL)}
 else{
    if(input$cat == 'All'){data$Category <- 'All'}
    else{data <- data[data$Category == input$cat, ]}
    if(input$user == 'All'){data$User <- 'All'}
    else{data <- data[data$User== input$user, ]}
    if(input$sub == 'All'){data$Subcategory <- 'All'}
    else{data<- data[data$Subcategory == input$sub, ]}
     }
 aggregate.data = aggregate(.~Category+Subcategory+User, data, sum)
})

以这种方式,如果用户和子类别输入为“全部”且类别列为“A”,则首先针对包含“A”和“全部”和“全部”的所有行过滤数据,然后生成的数据集为汇总在这三列上。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2019-06-12
    • 1970-01-01
    • 1970-01-01
    • 2021-12-23
    • 2018-10-03
    • 2018-10-16
    • 1970-01-01
    相关资源
    最近更新 更多