如何在Plotly中不依赖ggplotly实现按两组分组的叠加条形图(复刻ggplot效果)
如何在Plotly中不依赖ggplotly实现按两组分组的叠加条形图(复刻ggplot效果)
嘿,我懂你想要完全用Plotly复刻出ggplot做的那种分组叠加条形图,而且不想靠ggplotly转译的心情!那咱们一步步来实现,先从数据预处理开始,再到Plotly的可视化代码~
第一步:预处理数据(先聚合再转宽格式)
首先得把原始的长格式数据转换成适合Plotly做叠加条形的结构,就像你提到的那样,先按三个分组字段统计数量,再转成宽格式:
library(data.table) library(plotly) # 生成原始数据(和你提供的一致) n = 7200 n1 = 4/3*n n2 = 2*n dt = data.table(x = sample(rep(c("0-20", "21-40", "41-60", "61-80"), n)), group1 = sample(rep(c("A", "B", "C"), n1)), group2 = sample(rep(c(0, 1), n2)) ) setorder(dt, x, group1, group2) dt[, x := factor(x)] dt[, group1 := factor(group1)] dt[, group2 := factor(group2)] # 聚合统计数量 dt_agg = dt[, .N, by = .(x, group1, group2)] # 转成宽格式,方便Plotly处理叠加 dt_wide = dcast(dt_agg, x + group1 ~ group2, value.var = "N") # 把group1按逆序排列,对应ggplot里的fct_rev dt_wide[, group1 := forcats::fct_rev(group1)]
第二步:用Plotly实现复刻效果
接下来我们用Plotly的subplot来模拟ggplot的facet_grid行分面效果,每个group1类别对应一个子图,然后在每个子图里做group2的叠加条形,同时调整样式匹配你的ggplot效果:
# 先定义颜色,和你ggplot里的一致 fill_colors = c("#9c868b", "#038073") names(fill_colors) = c("0", "1") # 按group1拆分数据,生成每个子图的trace group_list = unique(dt_wide$group1) plot_list = lapply(group_list, function(g) { sub_data = dt_wide[group1 == g] # 第一个group2的条形(底层) trace0 = bar( x = sub_data$N, y = sub_data$x, orientation = "h", marker = list(color = fill_colors["0"]), showlegend = FALSE ) # 第二个group2的条形(叠加层) trace1 = bar( x = sub_data$`1`, y = sub_data$x, orientation = "h", marker = list(color = fill_colors["1"]), showlegend = FALSE ) # 组合子图,设置标题为group1的类别,放在左侧 subplot(trace0, trace1, shareY = TRUE, shareX = FALSE, titleX = FALSE, titleY = TRUE) %>% layout( title = list(text = g, x = -0.1, y = 0.5, xanchor = "right", yanchor = "middle"), yaxis = list(title = "", categoryorder = "array", categoryarray = sub_data$x), xaxis = list(title = "", position = 1) # x轴(对应ggplot的y轴)放在右侧 ) }) # 把所有子图垂直拼接,调整整体布局 final_plot = subplot(plot_list, nrows = length(group_list), shareX = TRUE, shareY = TRUE, margin = 0.05) %>% layout( barmode = "stack", # 设置叠加模式 xaxis = list(title = "Count"), showlegend = FALSE, margin = list(l = 100) # 给左侧的group1标题留足够空间 ) # 查看最终图 final_plot
这样做出来的效果就和你用ggplot生成的几乎一致了:横向的叠加条形、group1作为垂直分面(每个类别单独一块)、数值轴在右侧、没有图例,颜色也和你指定的完全匹配。
备注:内容来源于stack exchange,提问作者nimliug
相关产品推荐
相关产品推荐

