无y值时如何在ggplot密度图中使用geom_text_repel?
解决方法:手动计算密度数据再绘图
因为geom_line(stat = "density")是在绘图时自动计算密度值,不会把y(密度)暴露给后续图层,所以最直接的办法是先手动计算每个特征的密度数据,再用这个数据来画曲线和添加文本标签。
步骤1:手动计算密度数据
用dplyr分组后调用density()函数,把计算出的x(对应原数据的score)和y(密度值)整理成标准数据框:
library(tidyverse) library(ggrepel) # 计算每个特征的密度并整理数据 density_data <- feature1 %>% group_by(name) %>% # 对每个分组计算密度,保存为列表列 summarize(dens = list(density(value, bw = 0.5)), .groups = "drop") %>% # 展开密度结果的字段 unnest_wider(dens) %>% # 把x和y的向量展开成行 unnest(c(x, y)) %>% # 提前处理名称换行,避免重复计算 mutate(name_wrap = str_wrap(name, 20))
步骤2:用整理好的数据绘图
现在数据里已经有明确的x和y值,直接给geom_text_repel指定参数即可。下面示例是在每条密度曲线的峰值位置添加标签:
ggplot(density_data, aes(x = x, y = y, color = name_wrap)) + geom_line(size = 1) + geom_text_repel( aes(label = name_wrap), # 筛选每个曲线的峰值点作为标签位置 data = . %>% group_by(name_wrap) %>% filter(y == max(y)), size = 4, # 可以调整标签的偏移、方向等参数 nudge_y = 0.01 ) + labs(x = "score", color = "Features")
可选调整
- 如果不想在峰值加标签,也可以指定特定x值的位置,比如筛选
x == 5(根据你的score范围调整),或者取曲线的终点slice_max(x)。 - 可以通过
geom_text_repel的参数(比如nudge_x、direction)调整标签的位置,避免重叠。
内容的提问来源于stack exchange,提问作者Vladimir Mikheev
相关产品推荐
相关产品推荐

