Использование динамических фильтров для агрегирования данных в R Shiny - PullRequest
1 голос
/ 31 октября 2019

У меня есть данные в этом формате:

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

Я кодировал 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')

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 , когда пользователь вводит аргумент «Все». ,Например, если пользователь вводит «Все» для подкатегории и пользователя и «А» для категории, таблица выходных данных должна выглядеть следующим образом:

Category Subcategory   User   Count1    Count2
  A           All      All     7700      5500

или

Category  Count1    Count2
  A        7700      5500

Я могу написать условия if-else для этого, но в реальных данных есть 6-8 фильтров, и мне интересно, есть ли более простой способ агрегирования данных без записи элементов управления if-else для всех комбинаций агрегации (например, агрегата) Новые пользователи Все Категории и подкатегории или Агрегированы Все Категории, подкатегории и пользователи и т. д.).

Ответы [ 2 ]

1 голос
/ 05 ноября 2019

вы можете попробовать что-то подобное внутри 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.

0 голосов
/ 05 ноября 2019

Я добавил "" в качестве значения по умолчанию для фильтров ...

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

... и изменил значения столбцов на основе ввода пользовательского интерфейса.

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)
})

Таким образом, если входные данные пользователя и подкатегории «Все», а столбец «Категория» - «А», данные сначала фильтруются по всем строкам, содержащим «А» и «Все» и «Все», а затем результирующие данные. набор агрегируется по этим трем столбцам.

...