You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Shiny的reactive函数内使用group_by分组数据并计算组占比

问题解决:Shiny reactive中dplyr分组计算占比报错处理

核心问题原因

你遇到的报错本质是dplyr非标准评估的问题:在reactive函数中直接传入Shiny的input变量作为分组列时,dplyr默认会把input变量识别为普通字符串而非数据框的列名,才会出现无法对函数/字符串执行分组的错误。

你现有调整后可以运行的代码是通过data[[input$catgroup]]提取列值实现分组,虽然可以生效,但需要后续手动重命名列,有更简洁的规范写法。

优化后的实现方案

使用dplyr的{{ }}(双大括号运算符,也叫embrace运算符)直接解析动态传入的列名,无需后续手动修改列名,代码可读性和稳定性更高:
仅需要修改你的reactive部分代码即可:

datagr <- reactive({
  data %>% 
    # 用{{}}包裹动态列名,dplyr会自动解析为对应列
    group_by({{input$catgroup}}, sport,starter) %>%
    summarize(n = n(), .groups="drop")  %>%
    group_by(sport)%>%
    mutate(
      groupcount = sum(n),
      pog = paste0(round(100*n/groupcount,2),'%')
    ) %>%
    # 直接把动态列重命名为后续绘图需要的catgroup
    rename(catgroup = {{input$catgroup}})
})

对应的绘图部分也可以简化,不需要再手动改列名:

output$myplot <-  renderPlotly({
  plot_ly(datagr(), x = ~sport, y = ~n, type = "bar", color=~catgroup,  colors="Dark2") %>%
    layout(barmode = 'group')
})

你提供的原有可运行代码参考

静态分组占比计算代码

library(flexdashboard)
library(dplyr)
library(shiny)
library(plotly)


gender<-c("Male","Female","Female","Female","Male","Male","Male","Male","Female","Female")
age<-c(18,19,18,20,21,19,21,20,21,18)
sport<-c("Basketball","Basketball","Baseball/Softball","Basketball","Soccer","Baseball/Softball","Basketball","Soccer","Soccer","Soccer")
starter<-c("Yes","No","Yes","Yes","Yes","No","Yes","Yes","No","No")


data<-data.frame(gender,sport,starter)

datagr <- data %>%
  group_by(gender,age,sport,starter) %>%
  dplyr::summarise(n=n(), .groups="drop") %>%
  group_by(sport)%>%
  mutate(groupcount=sum(n)) %>%
  mutate(pog=paste0(round(100*n/groupcount,2),'%'))

datagr

静态代码输出结果

gender sport             starter     n groupcount pog  
  <chr>  <chr>             <chr>   <int>      <int> <chr>
1 Female Baseball/Softball Yes         1          2 50%  
2 Female Basketball        No          1          4 25%  
3 Female Basketball        Yes         1          4 25%  
4 Female Soccer            No          2          4 50%  
5 Male   Baseball/Softball No          1          2 50%  
6 Male   Basketball        Yes         2          4 50%  
7 Male   Soccer            Yes         2          4 50%  

原有可运行的Shiny完整代码

library(flexdashboard)
library(dplyr)
library(shiny)
library(plotly)


gender<-c("Male","Female","Female","Female","Male","Male","Male","Male","Female","Female")
age<-c("18","19","18","20","21","19","21","20","21","18")
sport<-c("Basketball","Basketball","Baseball/Softball","Basketball","Soccer","Baseball/Softball","Basketball","Soccer","Soccer","Soccer")
starter<-c("Yes","No","Yes","Yes","Yes","No","Yes","Yes","No","No")


data<-data.frame(gender,age, sport,starter)


cat.Variables <- c('gender', 'age')



ui <- fluidPage(
  
  sidebarPanel(
    selectInput('catgroup', choices = cat.Variables, label = 'Select filter options:'), 
    conditionalPanel(condition = "input.catgroup != '-'",
                     uiOutput("select_catgroup")
                    )
  ),
  mainPanel(plotlyOutput("myplot"))
  
)


server <- function(input, output) {
  

    
    datagr <- reactive({
      
      data %>% 
        group_by(data[[input$catgroup]], sport,starter) %>%
        summarize(n = n(), .groups="drop")  %>%
        group_by(sport)%>%
        mutate(groupcount=sum(n)) %>%
        mutate(pog=paste0(round(100*n/groupcount,2),'%')) })
    
        
    output$myplot <-  renderPlotly({
      datagrt <- datagr()
      colnames(datagrt) <- c("catgroup","sport","starter","n","groupcount","pog")
      plot_ly(datagrt, x = ~sport, y = ~n, type = "bar", color=~catgroup,  colors="Dark2") %>%
        layout(barmode = 'group')
    })
    
    
    
  
  
}

shinyApp(ui, server)

内容的提问来源于stack exchange,提问作者excelater

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.05 12:36:02