【问题标题】:R ggplot2 ggrepel - label a subset of points while being aware of all pointsR ggplot2 ggrepel - 在知道所有点的同时标记点的子集
【发布时间】:2018-09-19 02:57:25
【问题描述】:

我有一个相当密集的散点图,我正在使用 R 'ggplot2' 构建,我想使用 'ggrepel' 标记点的子集。我的问题是我想在散点图中绘制所有点,但只用 ggrepel 标记一个子集,当我这样做时,ggrepel 在计算放置标签的位置时不会考虑图中的其他点,这会导致到与绘图上其他点重叠的标签(我不想标记)。

这是一个说明问题的示例图。

# generate data:
library(data.table)
library(stringi)
set.seed(20180918)
dt = data.table(
  name = stri_rand_strings(3000,length=6),
  one = rnorm(n = 3000,mean = 0,sd = 1),
  two = rnorm(n = 3000,mean = 0,sd = 1))
dt[, diff := one -two]
dt[, diff_cat := ifelse(one > 0 & two>0 & abs(diff)>1, "type_1",
                        ifelse(one<0 & two < 0 & abs(diff)>1, "type_2",
                               ifelse(two>0 & one<0 & abs(diff)>1, "type_3",
                                      ifelse(two<0 & one>0 & abs(diff)>1, "type_4", "other"))))]

# make plot
ggplot(dt, aes(x=one,y=two,color=diff_cat))+
  geom_point()

如果我只绘制我想要标记的点的子集,那么 ggrepel 能够以相对于其他点和标签不重叠的方式放置所有标签。

ggplot(dt[abs(diff)>2 & (!diff_cat %in% c("type_3","type_4","other"))], 
  aes(x=one,y=two,color=diff_cat))+
  geom_point()+
  geom_text_repel(data = dt[abs(diff)>2 & (!diff_cat %in% c("type_3","type_4","other"))], 
                  aes(x=one,y=two,label=name))

但是,当我想同时绘制这个数据子集和原始数据时,我会得到带有标签的重叠点:

# now add labels to a subset of points on the plot
ggplot(dt, aes(x=one,y=two,color=diff_cat))+
  geom_point()+
  geom_text_repel(data = dt[abs(diff)>2 & (!diff_cat %in% c("type_3","type_4","other"))], 
                  aes(x=one,y=two,label=name))

如何使点子集的标签不与原始数据中的点重叠?

【问题讨论】:

    标签: r ggplot2 plot ggrepel


    【解决方案1】:

    您可以尝试以下方法:

    1. 为原始数据中的所有其他点分配一个空白标签 (""),以便geom_text_repel 在相互排斥标签时将它们考虑在内;
    2. box.padding 参数从默认的0.25 增加到更大的值,以获得更大的标签之间的距离;
    3. 增加 x 轴和 y 轴限制,以便在标签的四个边有更多空间来排斥。

    示例代码(带有box.padding = 1):

    ggplot(dt, 
           aes(x = one, y = two, color = diff_cat)) +
      geom_point() +
      geom_text_repel(data = . %>% 
                        mutate(label = ifelse(diff_cat %in% c("type_1", "type_2") & abs(diff) > 2,
                                              name, "")),
                      aes(label = label), 
                      box.padding = 1,
                      show.legend = FALSE) + #this removes the 'a' from the legend
      coord_cartesian(xlim = c(-5, 5), ylim = c(-5, 5)) +
      theme_bw()
    

    这是另一个尝试,box.padding = 2:

    (注意:我使用的是 ggrepel 0.8.0。我不确定早期软件包版本是否具备所有功能。)

    【讨论】:

    • 很棒的解决方案!
    • 真的很好,我都不知道,谢谢分享
    • 很好的解决方案!你甚至回答了一些我不想问的问题:)。
    猜你喜欢
    • 1970-01-01
    • 2015-12-14
    • 1970-01-01
    • 1970-01-01
    • 2019-09-07
    • 1970-01-01
    • 1970-01-01
    • 2021-02-01
    • 2019-02-16
    相关资源
    最近更新 更多