PAYATHON 2026

如何减少 vegan RDA 图中的标签重叠或隐藏部分标签?

数据小陈

可以只显示部分标签,或让标签自动避让。现有代码使用 R 基础绘图,最直接的方法是只向 text() 传入需要标注的物种。如果希望自动调整标签位置,可以将提取出的坐标交给 ggplot2,再用 ggrepel::geom_text_repel() 添加标签。

标签位置可以调整,物种和样点的排序坐标应保持原样。

为什么缩写和固定偏移效果有限?

缩写可以缩短文字,但无法消除坐标密集造成的重叠。给所有标签加上相同的偏移,也不会增加标签之间的距离。

另外,原代码中的:

sc_sp + c(0.03, 0.09)

会按照 R 的矩阵存储顺序循环使用这两个数,不能可靠地表示“第一列加 0.03,第二列加 0.09”。应分别指定横纵坐标:

text(
  x = sc_sp[, 1] + 0.03,
  y = sc_sp[, 2] + 0.09,
  labels = rownames(sc_sp),
  col = "grey40",
  font = 2,
  cex = 0.8
)

这能修正偏移方式,但不会自动解决标签之间的重叠。

保留基础绘图:只标注部分物种

保留原来的 plot()、points() 和箭头代码,将物种标签对应的 text() 替换为下面这段:

# 示例:只标注距离原点最远的最多 15 个物种
n_label <- min(15L, nrow(sc_sp))
distance2 <- rowSums(sc_sp[, 1:2, drop = FALSE]^2)
keep <- head(order(distance2, decreasing = TRUE), n_label)

text(
  x = sc_sp[keep, 1] + 0.03,
  y = sc_sp[keep, 2] + 0.09,
  labels = rownames(sc_sp)[keep],
  col = "grey40",
  font = 2,
  cex = 0.8
)

物种点会全部保留,只减少标签数量。15L 是可以调整的显示数量,不是分析阈值。

按距离筛选是一种展示规则,不能说明物种具有统计显著性,也不能直接解释为生态学重要性。如果已经确定了需要讨论的物种,应按名称选择:

# 将示例名称替换为 rownames(sc_sp) 中的实际名称
label_species <- c("Species_A", "Species_B")
keep <- which(rownames(sc_sp) %in% label_species)

随后使用相同的 text() 代码添加标签。筛选后如果仍有少量文字重叠,可以单独调整位置。

使用 ggplot2 和 ggrepel 自动避让

如果希望标签自动移动,可以用下面的代码复用已有的三组坐标,重新绘制样点、物种点和解释变量箭头。需要先安装 ggplot2 和 ggrepel。

library(ggplot2)
library(ggrepel)

sites <- data.frame(
  x = sc_si[, 1],
  y = sc_si[, 2]
)

species <- data.frame(
  x = sc_sp[, 1],
  y = sc_sp[, 2],
  label = rownames(sc_sp)
)

bp <- data.frame(
  x = sc_bp[, 1],
  y = sc_bp[, 2],
  label = rownames(sc_bp)
)

ggplot() +
  geom_point(
    data = sites, aes(x, y),
    shape = 21, colour = "black", fill = "steelblue",
    size = 3
  ) +
  geom_point(
    data = species, aes(x, y),
    shape = 22, colour = "black", fill = "#f2bd33",
    size = 3
  ) +
  geom_segment(
    data = bp,
    aes(x = 0, y = 0, xend = x, yend = y),
    colour = "red",
    arrow = grid::arrow(length = grid::unit(0.2, "cm"))
  ) +
  geom_text_repel(
    data = species, aes(x, y, label = label),
    colour = "grey40",
    fontface = "bold",
    size = 3,
    box.padding = 0.4,
    point.padding = 0.2,
    max.overlaps = 10,
    seed = 42
  ) +
  geom_text(
    data = bp, aes(x, y, label = label),
    colour = "red",
    fontface = "bold",
    nudge_y = 0.03
  ) +
  coord_equal() +
  labs(
    x = colnames(sc_sp)[1],
    y = colnames(sc_sp)[2]
  ) +
  theme_classic()

box.padding 控制标签周围的留白,point.padding 控制标签与其对应点之间的留白。max.overlaps 用于跳过与过多对象重叠的标签,示例值 10 可以按图的密度调整。

如果需要尽量保留全部标签,可以设置:

max.overlaps = Inf

这会取消该参数对标签数量的筛除限制,但不能保证密集图中的全部文字都能排开。扩大输出图片或先筛选标签,通常更有效。

自动避让主要处理物种标签层。解释变量的红色文字由另一个图层绘制,仍需检查它是否与物种标签相撞。

还需要检查坐标范围和轴名称

原代码将横纵坐标范围都设置为 c(-1, 1)。应检查范围是否适合实际坐标,以及边缘是否有足够空间显示标签,以免文字被裁切。

轴名称也需要核对。如果 PFNA 是唯一的数值型解释变量,模型至多只有一个约束轴;第二个提取的轴可能是残差轴 PC1,不能直接写成 RDA2。可以查看:

colnames(sc_sp)
summary(spe.rda.signif)

再确认轴名称和百分比的计算依据。原代码没有给出 perc 的定义,因此无法判断现有百分比标注是否正确。

备注:内容仅供参考。