R Shiny中ggplotly图表空格千位分隔符显示异常求助
解决ggplotly中hover提示同时显示格式化代码与数值的问题
我在开发R Shiny应用,用ggplotly制作交互式柱状图,想把数值的千位分隔符设为空格。现有代码运行后,hover提示框最后一行能显示正确格式化的数值,但同时也会出现格式化代码,不知道怎么解决。
原代码如下:
mrg <- list(l=10, r=10, b=10, t=100, pad=1) output$sortie3_evo <- renderPlotly({ g <- ggplot(filtered_data_evo(), aes(x=Année.Scolaire, y= Nombre.élèves, fill=Secteur,label = format(as.numeric(..y..), nsmall=0, big.mark=" ")))+ stat_summary(fun = sum, geom = "bar", position = position_dodge(0.9))+ theme(axis.text.x = element_text(angle=25, hjust=1))+ facet_wrap(~ NiveauLV, ncol = 2) + xlab("") g <- ggplotly(g) %>% layout(margin = mrg) })
问题原因
直接在aes()的label参数中写入format(as.numeric(..y..), ...)这类表达式时,ggplot会将表达式本身和计算后的结果同时纳入hover提示内容——因为..y..是stat层的内部变量,ggplotly解析时无法自动区分表达式和最终数值。
解决方案
方案一:通过stat_summary定义自定义hover文本
在stat_summary中用text参数构建完整的hover提示内容,再指定ggplotly仅显示该文本:
mrg <- list(l=10, r=10, b=10, t=100, pad=1) output$sortie3_evo <- renderPlotly({ g <- ggplot(filtered_data_evo(), aes(x=Année.Scolaire, y=Nombre.élèves, fill=Secteur)) + stat_summary( fun = sum, geom = "bar", position = position_dodge(0.9), # 在stat层生成格式化后的完整hover文本 aes(text = paste0( "Année Scolaire: ", Année.Scolaire, "\n", "Secteur: ", Secteur, "\n", "Nombre élèves: ", format(..y.., nsmall=0, big.mark=" ") )) ) + theme(axis.text.x = element_text(angle=25, hjust=1)) + facet_wrap(~ NiveauLV, ncol = 2) + xlab("") ggplotly(g, tooltip = "text") %>% # 指定仅显示自定义text内容 layout(margin = mrg) })
方案二:提前计算汇总数据(更直观)
先通过分组汇总得到总和,再基于汇总数据绘图,避免依赖stat层的内部变量:
mrg <- list(l=10, r=10, b=10, t=100, pad=1) output$sortie3_evo <- renderPlotly({ # 提前计算各分组的学生总数,并格式化数值 summary_data <- filtered_data_evo() %>% group_by(Année.Scolaire, Secteur, NiveauLV) %>% summarise(Nombre.élèves = sum(Nombre.élèves), .groups = "drop") %>% mutate(Nombre.élèves_formatted = format(Nombre.élèves, nsmall=0, big.mark=" ")) g <- ggplot(summary_data, aes(x=Année.Scolaire, y=Nombre.élèves, fill=Secteur, text = paste0( "Année Scolaire: ", Année.Scolaire, "\n", "Secteur: ", Secteur, "\n", "Nombre élèves: ", Nombre.élèves_formatted ))) + geom_bar(stat = "identity", position = position_dodge(0.9)) + theme(axis.text.x = element_text(angle=25, hjust=1)) + facet_wrap(~ NiveauLV, ncol = 2) + xlab("") ggplotly(g, tooltip = "text") %>% layout(margin = mrg) })
测试数据
structure(list(Année.Scolaire = c("2018-2019", "2018-2019", "2018-2019", "2018-2019", "2018-2019", "2018-2019", "2018-2019", "2018-2019", "2018-2019", "2018-2019"), Secteur = structure(c(2L, 2L, 2L, 2L, 1L, 1L, 1L, 1L, 1L, 1L), .Label = c("PUBLIC", "PRIVE SOUS CONTRAT" ), class = "factor"), Département = c("ARDECHE", "ARDECHE", "HAUTE SAVOIE", "SAVOIE", "HAUTE SAVOIE", "HAUTE SAVOIE", "ISERE", "ISERE", "ISERE", "SAVOIE"), Cycle = c("Cycle 2", "Cycle 3", "Cycle 2", "Cycle 3", "Cycle 1", "Cycle 3", "Cycle 1", "Cycle 2", "Cycle 3", "Cycle 1" ), LV = c("Allemand LV1", "Allemand LV1", "Allemand LV1", "Allemand LV1", "Allemand LV1", "Allemand LV1", "Allemand LV1", "Allemand LV1", "Allemand LV1", "Allemand LV1"), Nombre.élèves = c(6, 6, 6, 324, 66, 3, 21, 258, 18, 204), NiveauLV = c("LV1", "LV1", "LV1", "LV1", "LV1", "LV1", "LV1", "LV1", "LV1", "LV1"), LV_recode = c("Allemand", "Allemand", "Allemand", "Allemand", "Allemand", "Allemand", "Allemand", "Allemand", "Allemand", "Allemand")), row.names = c(NA, 10L), class = "data.frame")
内容的提问来源于stack exchange,提问作者Chloé
相关产品推荐
相关产品推荐

