如何解决ggplot结合ggplotly绘制日期交互式直方图的子条堆叠问题
解决ggplotly日期直方图的堆叠异常问题
嘿,你遇到的这个问题我之前也碰到过——根源在于ggplot的分组逻辑:当你在aes()里加入text=as.character(fechas)时,ggplot会自动把每个单独的日期值作为分组依据,完全忽略了你设置的binwidth=7区间规则。这就导致原本该合并成单根柱子的周区间,被拆成了每个日期的小柱子堆叠起来,不管是纯ggplot还是ggplotly都会出现这个问题。
下面给你两种靠谱的解决方案:
方案1:手动计算直方图统计(推荐,可控性最强)
先提前计算好每个日期区间的计数,这样能完全掌控分组和tooltip的内容,避开ggplot自动分组的坑:
library(lubridate) library(ggplot2) library(ggplotly) library(dplyr) # 生成示例数据 Ejemplo <- data.frame(fechas = dmy("1-1-20")+sample(1:100,100, replace=T), valores=runif(100)) # 手动按周分组计算计数,并生成自定义tooltip文本 hist_data <- Ejemplo %>% # 将日期向下取整到每周起始日 mutate(week_start = floor_date(fechas, "week")) %>% group_by(week_start) %>% summarise(casos = n()) %>% # 自定义tooltip内容,清晰显示区间和计数 mutate(tooltip = paste0("区间: ", week_start, " ~ ", week_start + days(6), "\nNº casos: ", casos)) # 用geom_col绘制(因为已经是汇总好的统计数据) dibujo <- ggplot(hist_data, aes(x=week_start, y=casos, text=tooltip)) + theme_bw() + geom_col(fill="darkblue", color="black", width=7) + # width设为7匹配周区间宽度 labs(x="Fecha", y="Nº casos") + theme(axis.text.x=element_text(angle=60, hjust=1)) + scale_x_date(date_breaks = "weeks", date_labels = "%d-%m-%Y", limits=c(dmy("1-1-20"), dmy("1-4-20"))) # 调用ggplotly,指定tooltip显示我们自定义的text内容 ggplotly(dibujo, tooltip = "text")
方案2:利用ggplot的内置统计变量(无需手动汇总)
如果你不想提前处理数据,可以直接用ggplot绘制直方图时生成的内部统计变量(比如计数、区间中点)来定义tooltip,避免传入原始日期干扰分组:
library(lubridate) library(ggplot2) library(ggplotly) # 生成示例数据 Ejemplo <- data.frame(fechas = dmy("1-1-20")+sample(1:100,100, replace=T), valores=runif(100)) # 基础直方图,不在aes里加text dibujo <- ggplot(Ejemplo, aes(x=fechas)) + theme_bw() + geom_histogram(binwidth=7, fill="darkblue", color="black") + labs(x="Fecha", y="Nº casos") + theme(axis.text.x=element_text(angle=60, hjust=1)) + scale_x_date(date_breaks = "weeks", date_labels = "%d-%m-%Y", limits=c(dmy("1-1-20"), dmy("1-4-20"))) # 直接用ggplotly的tooltip参数调用内置统计变量 ggplotly(dibujo, tooltip = c("x", "count")) # 如果想自定义tooltip文本,用after_stat()访问统计变量 dibujo_custom <- ggplot(Ejemplo, aes(x=fechas, text=paste0("区间中点: ", after_stat(x), "\nNº casos: ", after_stat(count)))) + theme_bw() + geom_histogram(binwidth=7, fill="darkblue", color="black") + labs(x="Fecha", y="Nº casos") + theme(axis.text.x=element_text(angle=60, hjust=1)) + scale_x_date(date_breaks = "weeks", date_labels = "%d-%m-%Y", limits=c(dmy("1-1-20"), dmy("1-4-20"))) ggplotly(dibujo_custom, tooltip = "text")
这里的after_stat()是关键,它能让你访问ggplot在绘制统计图层(比如geom_histogram)时自动计算的变量,这样既不会破坏直方图的区间合并,又能给tooltip提供正确的信息。
两种方法都能解决你遇到的堆叠问题,按需选就行~
内容的提问来源于stack exchange,提问作者skan
相关产品推荐
相关产品推荐

