ggrepel在ggtern三元图中失效,求替代标签避让方案
解决方案:三元图标签避让的替代方法
针对你在Shiny应用中使用ggtern绘制三元图时,geom_text_repel标签消失、geom_label_repel不兼容的问题,提供两种可行方案:
方案一:手动微调标签位置(适合少量重叠点)
如果重叠点数量不多,直接给标签对应的三元坐标添加微小偏移即可让标签自然分开,这种方法简单直接,适合Shiny中动态点数量较少的场景:
require(ggplot2) require(ggtern) require(dplyr) # 原始数据处理 USDA.LAB <- USDA %>% dplyr::group_by(Label) %>% dplyr::summarise( Clay = mean(Clay), Sand = mean(Sand), Silt = mean(Silt) ) USDA.LAB$Angle = 0 USDA.LAB$Angle[which(USDA.LAB$Label == 'Loamy Sand')] = -35 # 给重叠点添加坐标偏移 df <- data.frame( HORIZON = c("A", "B"), Sand = c(5, 5), Silt = c(5, 5), Clay = c(80, 80) ) %>% # 给两个点的Sand和Silt分别加减偏移量,避免标签重叠 mutate( Sand = Sand + c(2, -2), Silt = Silt + c(2, -2) ) # 绘制三元图 base <- ggplot(data = USDA, aes(y=Clay, x=Sand, z=Silt)) + coord_tern(L="x",T="y",R="z") + geom_polygon(alpha = 0.75, size = 0.5, color = 'black', aes(color=Label, fill=Label)) + geom_text(data = USDA.LAB, aes(label = Label, angle = Angle), color = 'black', size = 3.5) + theme_rgbw() + theme_showsecondary() + theme_showarrows() + custom_percent("Percent") + theme(legend.justification = c(0, 1), legend.position = c(0, 1), axis.tern.padding = unit(0.15, 'npc')) + labs(title = 'USDA Textural Classification Chart', fill = 'Textural Class', color = 'Textural Class') + geom_point(data=df, size=3) + # 使用偏移后的坐标绘制标签 geom_text(data=df, aes(label = HORIZON), size=4) base
方案二:结合ggrepel坐标计算与三元坐标转换(适合多重叠点)
如果需要智能避让大量重叠点,可以利用ggrepel的底层计算函数,先将三元坐标转换为笛卡尔坐标计算避让位置,再转回三元坐标:
require(ggplot2) require(ggtern) require(dplyr) require(ggrepel) # 原始数据处理 USDA.LAB <- USDA %>% dplyr::group_by(Label) %>% dplyr::summarise( Clay = mean(Clay), Sand = mean(Sand), Silt = mean(Silt) ) USDA.LAB$Angle = 0 USDA.LAB$Angle[which(USDA.LAB$Label == 'Loamy Sand')] = -35 df <- data.frame( HORIZON = c("A", "B"), Sand = c(5, 5), Silt = c(5, 5), Clay = c(80, 80) ) # 1. 将三元坐标转换为笛卡尔坐标 cart_coords <- tern2cart( x = df$Sand, y = df$Clay, z = df$Silt, L="x", T="y", R="z" ) df_cart <- data.frame( x = cart_coords$x, y = cart_coords$y, HORIZON = df$HORIZON ) # 2. 用ggrepel计算避让后的笛卡尔坐标位置 repel_result <- repel_boxes( data = df_cart, x = x, y = y, labels = HORIZON, point.size = 3, label.size = 4, force = 5 # 调整避让力度,数值越大避让越明显 ) # 3. 将避让后的笛卡尔坐标转回三元坐标 tern_coords <- cart2tern( x = repel_result$x, y = repel_result$y, L="x", T="y", R="z" ) df_repel <- df %>% mutate( Sand = tern_coords$x, Clay = tern_coords$y, Silt = tern_coords$z ) # 绘制三元图 base <- ggplot(data = USDA, aes(y=Clay, x=Sand, z=Silt)) + coord_tern(L="x",T="y",R="z") + geom_polygon(alpha = 0.75, size = 0.5, color = 'black', aes(color=Label, fill=Label)) + geom_text(data = USDA.LAB, aes(label = Label, angle = Angle), color = 'black', size = 3.5) + theme_rgbw() + theme_showsecondary() + theme_showarrows() + custom_percent("Percent") + theme(legend.justification = c(0, 1), legend.position = c(0, 1), axis.tern.padding = unit(0.15, 'npc')) + labs(title = 'USDA Textural Classification Chart', fill = 'Textural Class', color = 'Textural Class') + geom_point(data=df, size=3) + # 使用避让后的三元坐标绘制标签 geom_text(data=df_repel, aes(label = HORIZON), size=4) base
注意事项
- 方案二中的
force参数可以调整标签避让的力度,根据实际点的密度调整数值; - 确保Shiny应用中加载了所有依赖包:
ggplot2、ggtern、dplyr、ggrepel; - 如果点落在坐标轴上,可以在坐标转换后额外添加少量偏移,避免标签超出图范围。
内容的提问来源于stack exchange,提问作者Kerry Kuntz
相关产品推荐
相关产品推荐

