ggplot2叠加小提琴图时部分箱线图与散点未显示的问题求助
ggplot2叠加小提琴图时部分箱线图与散点未显示的问题求助
您好!我来帮您分析一下这个问题:
问题原因
您当前的代码里,每次添加geom_violin时都指定了新的y映射(比如y = Wrist、y = Tip_of_middle_finger),但紧接着的geom_boxplot和geom_jitter没有同步更新y的映射,它们依然沿用了最初ggplot定义的aes(Time, Elbow)里的Elbow作为y轴数据,所以只有第一个小提琴图(Elbow)上显示了箱线图和散点,后面的Wrist、Tip对应的箱线和散点其实是画在Elbow的y值位置上,自然看不到啦。
解决方案
推荐把数据转换成**长格式(tidy data)**来绘图,这是ggplot2最适配的数据结构,能避免重复写冗余的图层代码,也更不容易出错:
步骤1:转换数据格式
先用tidyr包的pivot_longer把宽数据转成长数据,把三个部位的数值整合到一列,同时新增一列标记部位名称:
library(ggplot2) library(ggbreak) library(tidyr) # 需要加载这个包做数据重塑 # 假设您的fakebis数据已经存在 data <- fakebis %>% pivot_longer( cols = c(Elbow, Wrist, `Tip of middle finger`), names_to = "Body_Part", values_to = "Position" ) positions <- c("Pre", "Post")
步骤2:绘制图形
现在只需要一次调用geom_violin、geom_boxplot、geom_jitter,用Body_Part映射颜色,就能在每个Time(Pre/Post)位置上叠加三个部位的图形:
p <- ggplot(data, aes(x = Time, y = Position, colour = Body_Part)) + theme_classic() + xlab("Measurement time relative to tool-use session") + scale_x_discrete(limits = positions) + scale_y_break(c(4, 27)) + ylab("Reported position (cm)") + # 叠加小提琴图,用position_dodge让多个图形横向对齐 geom_violin(alpha = .5, size = 2, trim = FALSE, position = position_dodge(width = 0.8)) + # 叠加箱线图,和小提琴图的dodge宽度保持一致 geom_boxplot(width = 0.1, position = position_dodge(width = 0.8)) + # 叠加散点,用jitterdodge实现散点分散且对齐 geom_jitter(shape = 16, position = position_jitterdodge(jitter.width = 0.2, dodge.width = 0.8)) p
如果坚持用宽格式绘图(不推荐)
您需要给每个geom_boxplot和geom_jitter都明确指定对应的y值,比如:
# 初始代码修改版 p <- ggplot(data, aes(Time, Elbow))+ theme_classic() + xlab("Measurment time relative to tool-use session")+ scale_x_discrete(limits = positions)+ scale_y_break(c(4, 27))+ ylab("Reported position (cm)") # Elbow的图层 p <- p + geom_violin(aes(colour = "1"), alpha = .5, size=2,trim=FALSE)+ geom_boxplot(width=0.1)+ geom_jitter(shape=16, position=position_jitter(0.2)) # Wrist的图层,每个geom都指定y=Wrist q <- p + geom_violin(aes(y = Wrist, colour = "2"), alpha = .5, size=2,trim=FALSE)+ geom_boxplot(aes(y = Wrist), width=0.1)+ geom_jitter(aes(y = Wrist), shape=16, position=position_jitter(0.2)) # Tip的图层,每个geom都指定y=Tip_of_middle_finger q <- q + geom_violin(aes(y = Tip_of_middle_finger, colour = "3"), alpha = .5, size=2,trim=FALSE)+ geom_boxplot(aes(y = Tip_of_middle_finger), width=0.1)+ geom_jitter(aes(y = Tip_of_middle_finger), shape=16, position=position_jitter(0.2)) q
不过这种方式代码冗余度高,后期修改也麻烦,还是更推荐用长格式的方法哦!
备注:内容来源于stack exchange,提问作者Ishan
相关产品推荐
相关产品推荐

