基于ggplot2编写函数为数据框每行绘制堆叠条形图
解决R语言为数据框每行绘制堆叠条形图的问题
嘿,我来帮你搞定这个问题!你之前用apply的方式出错,核心原因是apply按行处理时会把数据转换成无结构的原子向量,丢失了列名和数据框的格式,导致melt函数无法识别id.vars="id"。下面给你两种可行的解决方案:
方法一:使用by函数(基础R风格)
by函数可以按指定分组(这里按id,也就是每行)保留数据框结构,完美适配你的绘图函数:
library(ggplot2) library(reshape2) # 推荐用reshape2替代旧版reshape,更稳定 # 你的原始数据框 df1 <- data.frame(id=c("a","b","c","d"), var1=c(2,4,4,5), var2=c(5,6,2,6), var3=c(5,3,2,1)) # 修正后的绘图函数:先把行向量转回带列名的数据框 my.func <- function(x){ # 将传入的行向量转换为数据框,t()转置是因为行向量转数据框会变成列 xx <- as.data.frame(t(x)) xx.m <- melt(xx, id.vars = "id") ggplot(xx.m, aes(x = id, y = value, fill = variable)) + geom_bar(stat='identity') + coord_flip() + ggtitle(paste("堆叠条形图 - ID:", xx$id)) # 加标题区分每个图 } # 按id分组处理每行数据 results <- by(df1, df1$id, my.func)
方法二:使用purrr::map(tidyverse风格)
如果你习惯tidyverse的工作流,用purrr的map函数会更简洁,先把数据框拆成每行一个子数据框的列表,再逐个绘图:
library(purrr) library(ggplot2) library(reshape2) df1 <- data.frame(id=c("a","b","c","d"), var1=c(2,4,4,5), var2=c(5,6,2,6), var3=c(5,3,2,1)) # 把数据框按id拆分成每行一个数据框的列表 df_row_list <- split(df1, df1$id) # 遍历列表绘图 results <- map(df_row_list, function(row_df) { row_melt <- melt(row_df, id.vars = "id") ggplot(row_melt, aes(x = id, y = value, fill = variable)) + geom_bar(stat='identity') + coord_flip() + ggtitle(paste("堆叠条形图 - ID:", row_df$id)) })
为什么原来的apply不行?
当你执行apply(df1, 1, my.func)时,apply会把每一行转换成没有列名的原子向量(比如第一行变成c("a", 2, 5, 5)),此时你的my.func里的x不是数据框,也没有id这个列,melt自然会报错。
内容的提问来源于stack exchange,提问作者JoeyMcDougalhauser
相关产品推荐
相关产品推荐

