在ggtitle中访问图表数据

9

我想知道是否有可能在ggplot2图表的标题中访问提供的数据的列。类似这样:

ggplot(mpg %>% filter(manufacturer == 'audi'), 
  aes(x = hwy, y = displ, label = model)) + 
    geom_point() + 
    geom_text(data = . %>% filter(hwy > 28)) + 
    ggtitle(unique(.$manufacurer))

我经常像上面的示例一样创建绘图来仅绘制子集,并希望能自动标记子集。目前,.ggtitle 中将不被识别,但在 geom-text 中却可以工作。 编辑: 由于我从 @Brian 获得了一个非常好的评论和重复标记,那么在 dplyr::group_by 函数中是否有使用这个 {} 技巧的解决方案?这在某种程度上是无法正常工作的。我想为每个组创建单独的图形,但似乎只有完整的数据框进入了 ggplot 调用。
mpg %>%
  group_by(manufacturer) %>% {
    ggplot(., aes(cyl, displ, color=manufacturer)) +
      geom_point() + 
      ggtitle(unique(.$manufacturer))
  }

它显示的是奥迪,但在同一个图表中打印了所有制造商。

2
也许你可以将其分配给一个对象,如 p <- ggplot(...) + geom_text(...); 然后提取数据,如 p + ggtitle(unique(p$data$manufacturer)) - akrun
听起来是个不错的解决方法。我为什么不能用“.”访问数据,有任何逻辑上的原因吗? - drmariod
1
最近有人问了一个类似的问题。但是目前还没有解决方案。 - Roman
我认为这个类是不同的,即Layer、LayerInstance、ggproto,用于提取数据。 - akrun
1
@akrun 看起来很厉害 ggplot(mpg %>% filter(manufacturer == 'audi'), aes(x = hwy, y = displ, label = model, title=quo_name(unique(manufacturer)))) + geom_point() + geom_text(data = . %>% filter(hwy > 28)) - Roman
显示剩余5条评论
3个回答

3

由于无法在 aes() 外部进行管道传输,因此我建议尝试以下方法。

ggplot(mpg %>% filter(manufacturer == 'audi'), 
       aes(x = hwy, y = displ, label = model)) + 
  geom_point() + 
  geom_text(data = . %>% filter(hwy > 28)) +
  facet_wrap(~manufacturer)+
  theme(strip.background = element_blank(),
        strip.text = element_text(hjust = 0, size = 14))

enter image description here

这个想法是使用具有空白带背景的 facet。如果有更多的名称或变量,就必须使用例如 mutate(gr = "title") 创建一个额外的 faceting 变量。
mpg %>% 
  mutate(title="This is my plot") %>% 
ggplot(aes(x = hwy, y = displ, col=manufacturer)) + 
  geom_point() + 
  facet_wrap(~title)+
  theme(strip.background = element_blank(),
        strip.text = element_text(hjust = 0, size = 14))

编辑

由于您在这里提出了第二个问题,这里有两种解决方案可用于为每个组创建单独的绘图。

# first solution
p <- mpg %>%
  group_by(manufacturer) %>% 
     do(plots= ggplot(., aes(cyl, displ)) +
      geom_point() + 
      ggtitle(unique(.$manufacturer))
   )
p %>% slice(1) %>% .$plots


# second solution
mpg %>%
  nest(-manufacturer) %>%
  mutate(plot = map2(data, manufacturer, ~ggplot(data=.x,aes(cyl, displ))+
           geom_point() +
           ggtitle(.y))) %>% 
  slice(1) %>% .$plot 

或者使用保存数据

map2(paste0(p$manufacturer, ".pdf"), p$plots, ggsave)

我之前已经用过这个方法来解决问题,但从未想过去掉背景颜色。这是个好主意,实际上这已经足够了,因为这些图表通常并非出于生产目的。 - drmariod

1

这里有两种使用split的方法。你可以使用split将数据框拆分成基于变量的命名数据框列表。因此,调用split(mpg, .$manufacturer)会给你一个数据框列表,其中每个数据框都与制造商相关联,例如split_df$audi是由Audi制造的所有观察结果的数据框。

library(dplyr)
library(purrr)
library(ggplot2)

split_df <- split(mpg, .$manufacturer)

你可以通过调用列表中的单个项目来实现此操作的第一种方法。由于该列表是命名的,因此names(split_df)[1]将给出名称"audi"。
ggplot(split_df[[1]], aes(x = hwy, y = displ, label = model)) + 
    geom_point() + 
    geom_text(data = . %>% filter(hwy > 28)) +
    ggtitle(names(split_df)[1])

如果你想为多个制造商绘制图表,那么这种方法可能会很繁琐。当我做这件事时,我使用了purrr中的map函数。特别酷的是imap,它可以同时映射列表和其名称。在这里,我正在通过对数据框列表进行映射来创建一个图表列表;每个图表都从该列表项的名称获得标题。

plots <- imap(split_df, function(df, manufacturer) {
    ggplot(df, aes(x = hwy, y = displ, label = model)) +
        geom_point() +
        geom_text(data = . %>% filter(hwy > 28)) +
        ggtitle(manufacturer)
})

plots$audi

然后我可以从该绘图列表中提取特定项。如果您需要使用walk对它们进行映射并保存每个绘图或一部分绘图,或者如果您需要使用grid函数将它们排列成输出,或者其他任何purrr擅长的酷东西,这也很方便。

1

针对关于按变量分组生成图形的后续问题,我不确定应该如何做,以及group_by(foo) %>% ggplot()调用的输出是什么(逐个生成图形?存储它们?制作一个堆叠所有图形的大图?)。

你可以尝试使用lapply()来实现这一点。基于你找到的访问调用内部数据的解决方案:

library(dplyr)
library(ggplot2)

mfgs <- mpg %>% pull(manufacturer) %>% unique()
plot_list <- lapply(mfgs, function(mfg) {
  mpg %>%
  filter(manufacturer == mfg) %>% {
    ggplot(., aes(cyl, displ, color=manufacturer)) +
      geom_point() + 
      ggtitle(unique(.$manufacturer))
    }
})

从那里开始,您可以使用plot_list[[i]]访问给定的绘图,或者(a)传递命名向量而不是定义的mfgs,或者只是将列表的名称设置为所提供的制造商向量,这使您可以按名称调用绘图:

names(plot_list) <- mfgs
plot_list[["nissan"]]

希望这能帮到您。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接