5

我正在尝试用ggplot2R 制作一个带标签的气泡图。这是简化的场景:

我有一个包含 4 个变量的数据框:3 个定量变量 、xyz以及另一个标记点​​的变量 ,lab

我想制作一个散点图,其中位置由x和确定y,点的大小由 确定z。然后,我想将文本标签放置在点旁边(例如,点的右侧),而不会将文本重叠在点的顶部。

如果点的大小没有变化,我可以尝试geom_text通过添加缩放常数(例如aes(x=x+1, y=y+1))来简单地修改图层的美感。但是,即使在这种简单的情况下,我也无法正确定位文本,因为这些点不会随绘图的输出尺寸缩放。换句话说,点的大小在 500x500 和 1000x1000 的图中保持不变——它们不会随着输出图的尺寸放大。

因此,我认为我必须通过输出图的大小(例如尺寸)来缩放标签的位置,或者我必须以ggplot某种方式获取点的半径并移动我的文本标签。有没有办法做到这一点ggplot2

这是一些代码:

# Stupid data
df <- data.frame(x=c(1,2,3), 
                 y=c(1,2,3), 
                 z=c(1,2,1),
                 lab=c("a","b","c"), stringsAsFactors=FALSE)

# Plot with bad label placement
ggplot(aes(x=x, y=y), data=df) + 
  geom_point(aes(size=z)) + 
  geom_text(aes(label=lab), 
            colour="red") +
  scale_size_continuous(range=c(5, 50), guide="none")

编辑:我应该提一下,我在 geom_text 内部尝试过hjustvjust但它没有产生预期的效果。

# Trying hjust and vjust, but it doesn't look nice
ggplot(aes(x=x, y=y), data=df) + 
  geom_point(aes(size=z)) + 
  geom_text(aes(label=lab), hjust=0, vjust=0.5, 
            colour="red") +
  scale_size_continuous(range=c(5, 50), guide="none")

编辑:感谢 Henrik 和 shujaa,我设法得到了现在可以使用的东西。我会留下这个问题,以防有人分享更通用的解决方案。

只是我使用它的一个简介:我正在绘制一张地图,并用一个与观察到的降水量成正比的点来指示某些站点的降水量。我想以美观的方式在每个点旁边添加一个电台标签。我将为不同的区域制作更多这些图,并且我的输出图对于每个图可能具有不同的分辨率或比例(例如,由于不同的投影),因此需要一个通用的解决方案。position_jitter如果我周末有时间,我可能会尝试创建一个自定义,就像巴蒂斯特建议的那样。

4

3 回答 3

3

看来 position_*** 无法访问其他层使用的比例,所以这是不行的。您可以制作一个 GeomText 的克隆,根据映射的大小移动标签,但对于一个非常笨拙和脆弱的解决方案来说,这是一个很大的努力,

在此处输入图像描述

geom_shiftedtext <- function (mapping = NULL, data = NULL, stat = "identity", 
                       position = "identity", 
                       parse = FALSE, ...) { 
  GeomShiftedtext$new(mapping = mapping, data = data, stat = stat, position = position, 
               parse = parse, ...)
}
require(proto)
GeomShiftedtext <- proto(ggplot2:::GeomText, {
  objname <- "shiftedtext"
  draw <- function(., data, scales, coordinates, ..., parse = FALSE, na.rm = FALSE) {
    data <- remove_missing(data, na.rm, 
                           c("x", "y", "label"), name = "geom_shiftedtext")

    lab <- data$label
    if (parse) {
      lab <- parse(text = lab)
    }

    with(coord_transform(coordinates, data, scales),
         textGrob(lab, unit(x, "native") + unit(0.375* size, "mm"), 
                  unit(y, "native"), 
                  hjust=hjust, vjust=vjust, rot=angle, 
                  gp = gpar(col = alpha(colour, alpha), 
                            fontfamily = family, fontface = fontface, lineheight = lineheight))

         )
  }

})


df <- data.frame(x=c(1,2,3), 
                 y=c(1,2,3), 
                 z=c(1.2,2,1),
                 lab=c("a","b","c"), stringsAsFactors=FALSE)

ggplot(aes(x=x, y=y), data=df) + 
  geom_point(aes(size=z), shape=1) + 
  geom_shiftedtext(aes(label=lab, size=z),
            hjust=0, colour="red") +
  scale_size_continuous(range=c(5, 100), guide="none")
于 2013-10-31T00:28:41.387 回答
1

这不是一个非常通用的解决方案,因为您每次都需要对其进行调整,但是您应该能够将x一些线性值添加到文本的值中,具体取决于z.

我很幸运

ggplot(aes(x=x, y=y), data=df) + 
    geom_point(aes(size=z)) + 
    geom_text(aes(label=lab, x = x + .06 + .14 * (z - min(z))), 
              colour="red") +
    scale_size_continuous(range=c(5, 50), guide="none")

但是,由于字体大小取决于您的窗口大小,因此您需要确定输出大小并进行相应调整。我从最小点开始x = x + .05 + 0 * (z-min(z))并校准截距,然后当我对此感到满意时,我调整了最大点的线性项。

于 2013-10-30T22:09:27.223 回答
1

另一种选择。您的测试数据看起来不错,但您需要检查它的一般性。

dodge <- abs(scale(df$z))/4

ggplot(data = df, aes(x = x, y = y)) + 
  geom_point(aes(size = z)) +
  geom_text(aes(x = x + dodge), label = df$lab, colour = "red") +
  scale_size_continuous(range = c(5, 50), guide = "none")

更新 刚试过position_jitter,但width参数只取一个值,所以现在我不确定这个函数会有多大用处。但我会很高兴发现我错了。另一个小数据集的示例:

df3 <- mtcars[1:10, ]
ggplot(data = df3, aes(x = wt, y = mpg)) +
  geom_point(aes(size = qsec), alpha = 0.1) +
  geom_text(label = df3$carb, position = position_jitter(width = 0.1, height = 0)) +
  scale_size_continuous(range = c(5, 50), guide = "none")
于 2013-10-30T22:57:05.530 回答