R Shiny技术问题:基于多选框分组数据并绘制多折线图
R Shiny:按测试类型分组统计与折线图实现
核心问题拆解
你需要实现:针对选中的id,在指定日期区间内,按多选框选择的测试类型(A/B/C)分别统计每日记录数,并绘制多折线图。原数据为宽格式(每个测试类型对应多列),核心是先将数据转换为长格式,再按测试类型分组统计。
解决方案步骤
1. 数据格式转换(宽转长)
原数据中,batch_a_1/batch_a_2对应测试A,batch_b_1/batch_b_2对应测试B,batch_c_2对应测试C。需用tidyr::pivot_longer将这些列转为长格式,提取测试类型,筛选出值为1的有效记录(代表该测试有记录)。
2. 结合Shiny输入过滤并统计
根据用户选择的id、日期区间、测试类型,过滤数据后,按date和test_type分组,统计每日各测试的记录总数。
3. 绘制多折线图
用ggplot2绘制折线图,不同测试类型用不同颜色区分。
完整Shiny示例代码
library(shiny) library(tidyverse) # 模拟数据集 mydata <- tibble( id = c("rec1", "rec2", "rec3", "rec1", "rec1", "rec2", "rec3", "rec3"), date = as.Date(c("2022-01-01", "2022-01-03", "2022-01-01", "2022-01-03", "2022-01-01", "2022-01-03", "2022-01-01", "2022-01-03")), batch_a_1 = c(1,0,1,0,1,0,1,0), batch_a_2 = c(0,1,0,1,0,1,0,1), batch_b_1 = c(1,0,1,0,1,0,1,0), batch_b_2 = c(0,0,0,1,0,0,0,1), batch_c_2 = c(1,0,0,0,0,1,0,0) ) ui <- fluidPage( selectInput("id", "选择ID", choices = unique(mydata$id)), dateRangeInput("Dates", "选择日期区间", start = min(mydata$date), end = max(mydata$date)), checkboxGroupInput( inputId = "test", choices = c("A", "B", "C"), selected = c("A", "B", "C"), label = "选择测试类型" ), plotOutput("test_trend") ) server <- function(input, output) { # 处理数据:转换格式+过滤+统计 processed_data <- reactive({ mydata %>% # 宽转长:提取测试类型,筛选值为1的记录 pivot_longer(cols = starts_with("batch_"), names_to = "test_type", values_to = "has_record") %>% mutate(test_type = str_extract(test_type, "[a-z]") %>% toupper()) %>% # 提取A/B/C filter(has_record == 1) %>% # 应用Shiny输入过滤 filter( id == input$id, test_type %in% input$test, date >= input$Dates[1], date <= input$Dates[2] ) %>% # 按日期和测试类型统计总数 count(date, test_type, name = "record_count") }) # 绘制折线图 output$test_trend <- renderPlot({ processed_data() %>% ggplot(aes(x = date, y = record_count, color = test_type, group = test_type)) + geom_line(size = 1) + geom_point() + labs(x = "日期", y = "记录总数", color = "测试类型") + theme_minimal() }) } shinyApp(ui, server)
关键代码解释
- 宽转长:
pivot_longer将所有batch_开头的列转为长格式,str_extract从列名中提取测试类型(A/B/C),并筛选出has_record == 1的有效记录。 - 过滤逻辑:直接按
test_type %in% input$test筛选选中的测试类型,同时匹配id和日期区间。 - 分组统计:
count(date, test_type)自动按日期和测试类型分组,统计每组的记录数。 - 折线图绘制:用
color = test_type区分不同测试类型的折线,group = test_type确保每个测试类型单独成线。
注意事项
- 如果原数据中测试列的命名规则不同(比如不是
batch_x_*),需要调整str_extract的正则表达式,确保正确提取测试类型。 - 若日期区间内某测试类型无记录,折线图会自动忽略该类型,可通过
complete(date, test_type, fill = list(record_count = 0))补全0值,让折线显示为0。
内容的提问来源于stack exchange,提问作者akang
相关产品推荐
相关产品推荐

