【问题标题】:Showing separate legend for a geom_text layer?显示 geom_text 图层的单​​独图例?
【发布时间】:2012-05-09 02:37:13
【问题描述】:

我有以下情节:

library(ggplot2)

ib<- data.frame(
  category =   factor(c("Cat1","Cat2","Cat1", "Cat1", "Cat2","Cat1","Cat1", "Cat2","Cat2")),
  city =       c("CITY1","CITY1","CITY2","CITY3", "CITY3","CITY4","CITY5", "CITY6","CITY7"),
  median =     c(1.3560, 2.4830, 0.7230, 0.8100, 3.1480, 1.9640, 0.6185, 1.2205, 2.4000),
  samplesize = c(851, 1794,   47,  189,  185,    9,   94,   16,   65)
  )


p<-ggplot(data=ib, aes(x=city, y=category, size=median, colour=category, label=samplesize)) +
  geom_point(alpha=.6) +
  scale_area(range=c(1,15)) +
  scale_colour_hue(guide="none") +
  geom_text(aes(size = 1), colour="black")
p

(我正在绘制与中值成比例的圆圈并覆盖代表样本大小的文本标签。图片位于http://imgur.com/T82cF

有什么办法可以分开这两个传说吗?我希望一个图例(标记为“中位数”)给出圆圈的比例,另一个图例带有一个字母“a”(甚至更好的数字),我可以将其标记为“样本大小”。由于这两个属性没有任何关系,因此将它们捆绑在同一个图例中是没有意义的。

我尝试了各种组合,但我能想到的最好的方法就是完全失去文字图例:)

感谢您的回答!

【问题讨论】:

  • 我认为挑战将是尝试应用两种不同大小的映射。请参阅@joran 的 cmets here 和解决方案(参考不同的颜色映射)。但我不明白如何将这种解决方案轻松应用于您的问题。
  • 鉴于kohske's comments here,我更改了绘图,以便绘制大写“N”而不是小写“a”。

标签: r ggplot2


【解决方案1】:

这实际上并没有直接解决您的问题,但它我可能会如何创建具有您描述的一般特征的图表:

ib$ss <- paste("n = ",ib$samplesize,sep = "")

ggplot(data=ib, aes(x=city, y=category, size=median, colour=category, label=ss)) +
  geom_point(alpha=.6) +
  geom_text(size = 2, vjust = -1.2,colour="black") +
  scale_colour_hue(legend = FALSE)

我删除了 scale_area 部分,因为我不确定它的用途是什么,它给我带来了错误。

所以这里的基本原理是样本量信息对我来说更像是一种注释,而不是值得拥有自己的规模和传说的东西。当然,意见可能会有所不同,但我想我会把它放在那里以防你觉得它有用。

【讨论】:

  • 感谢@joran,这是可行的,但是,我的最终情节(大约 30 个城市和约 100 个类别)的空间非常有限,所以我更愿意描述这些数字的含义剧情之外。我同意这不是最好的解决方案,但我负担不起情节本身的那么多文字......
  • @Krizbi 我想。不过,在绘图上绘制 > (30 x 100) 个单独的数字是否比在每个数字前面加上“n =”更易读?
  • 你说得有道理——当然我已经在这个情节的“信息过载”区域(即使没有数字):)。因此,我希望在额外的文本中尽可能地简朴。 “n =”平均为一个 2-3 位数的数字添加 4 个字符空格,所以我认为影响和视觉混乱会相当大。想想我想要实现的元素周期表中的数据(例如:ptable.com),每个元素都有几条信息,我们有一个关于如何阅读它们的视觉指南(第二个框在第一行)。
【解决方案2】:

这也不能回答你的问题。我已将samplesize 留在圈内。此外,samplesize 对我来说更像是注释而不是图例。 但我认为您使用的是旧版本的ggplot2ggplot2 0.9.0 版有一些变化。我已经进行了以下更改。

p<-ggplot(data=ib, aes(x=city, y=category, size=median, colour=category, label=samplesize)) +
  geom_point(alpha=.6) +
  scale_area(range = c(1,15)) +  # range instead of to
  scale_colour_hue(guide = "none") +    # guide instead of legend
  geom_text(size = 2.5, colour="black")
 p

【讨论】:

  • 谢谢@Sandy,看来我使用的是旧版本 - 我确实升级了,但不知何故忘记重新启动 Rstudio :)
【解决方案3】:

更新 scale_area 已被弃用; scale_size 改为使用。 gtable 函数gtable_filter() 用于提取图例。并修改了用于替换其中一个图例中的默认图例键的代码。

如果您仍在寻找问题的答案,这里有一个似乎可以满足您的大部分需求,尽管它在某些地方有点小题大做。可以使用kohske's comment here更改图例中的符号

困难在于尝试应用两种不同大小的映射。因此,我将点尺寸映射保留在美学声明中,但从美学声明中删除了标签尺寸映射。这意味着必须根据样本大小(fsamplesize)的因子版本的离散值设置标签大小。结果图表几乎是正确的,除了未绘制标签大小(即样本大小)的图例。为了解决这个问题,我绘制了一个图表,其中包含根据样本大小的因子版本(但忽略点大小映射)的标签大小映射,以便提取其图例,然后可以将其插入回第一个图表中。

## Your data
ib<- data.frame(
  category =   factor(c("Cat1","Cat2","Cat1", "Cat1", "Cat2","Cat1","Cat1", "Cat2","Cat2")),
  city =       c("CITY1","CITY1","CITY2","CITY3", "CITY3","CITY4","CITY5", "CITY6","CITY7"),
  median =     c(1.3560, 2.4830, 0.7230, 0.8100, 3.1480, 1.9640, 0.6185, 1.2205, 2.4000),
  samplesize = c(851, 1794,   47,  189,  185,    9,   94,   16,   65)
  )

## Load packages
library(ggplot2)
library(gridExtra)
library(gtable)
library(grid)

##  Obtain the factor version of samplesize.   
ib$fsamplesize = cut(ib$samplesize, breaks = c(0, 100, 1000, Inf))

## Obtain plot with dot size mapped to median, the label inside the dot set 
## to samplesize, and the size of the label set to the discrete levels of the factor
## version of samplesize. Here, I've selected three sizes for the labels (3, 6 and 10)
## corresponding to samplesizes of 0-100, 100-1000, >1000. The sizes of the labels are
## set using three call to geom_text - one for each size.

p <- ggplot(data=ib, aes(x=city, y=category)) +
   geom_point(aes(size = median, colour = category), alpha = .6) +
   scale_size("Median", range=c(0, 15)) +
   scale_colour_hue(guide = "none") + theme_bw()

p1 <- p + 
  geom_text(aes(label = ifelse(samplesize > 1000, samplesize, "")), 
         size = 10, color = "black", alpha = 0.6) +
  geom_text(aes(label = ifelse(samplesize < 100, samplesize, "")), 
         size = 3, color = "black", alpha = 0.6) +
  geom_text(aes(label = ifelse(samplesize > 100 & samplesize < 1000, samplesize, "")), 
         size = 6, color = "black", alpha = 0.6)


## Extracxt the legend from p1 using functions from the gridExtra package
g1 = ggplotGrob(p1) 
leg1 = gtable_filter(g1, "guide-box")


## Keep p1 but dump its legend
p1 = p1 + theme(legend.position = "none")


## Get second legend - size of the label.
## Draw a dummy plot, using fsamplesize as a size aesthetic. Note that the label sizes are
## set to 3, 6, and 10,  matching the sizes of the labels in p1. 

dummy.plot = ggplot(data = ib, aes(x = city, y = category, label = samplesize)) +
  geom_point(aes(size = fsamplesize), colour = NA) +
  geom_text(show.legend = FALSE) + theme_bw() +
  guides(size = guide_legend(override.aes = list(colour = "black", shape = utf8ToInt("N")))) +
scale_size_manual("Sample Size", values = c(3, 6, 10),
     breaks = levels(ib$fsamplesize), labels = c("< 100", "100 - 1000", "> 1000"))

## Get the legend from dummy.plot using functions from the gridExtra package
g2 = ggplotGrob(dummy.plot) 
leg2 = gtable_filter(g2, "guide-box")


## Arrange the three components (p1, leg1, leg2) using functions from the gridExtra package
## The two legends are arranged using the inner arrangeGrob function. The resulting
## chart is then arranged with  p1 in the outer arrrangeGrob function.
ib.plot = arrangeGrob(p1, arrangeGrob(leg1, leg2, nrow = 2), ncol = 2, 
      widths = unit(c(9, 2), c("null", "null")))

## Draw the graph
grid.newpage()
grid.draw(ib.plot)

【讨论】:

  • 哇@Sandy,感谢您的努力!太好了,非常感谢!
  • 查看here 了解更可靠地处理图例宽度的方法。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2022-08-19
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-02-25
相关资源
最近更新 更多