如何从嵌套数据框中提取ggplot对象进行单独操作
问题原因
通过group_by() + nest() + map()生成的绘图列属于列表列:数据框每一行对应一个存储ggplot对象的列表元素。使用pull()提取筛选后的列表列时,哪怕筛选结果仅1行,返回值依然是长度为1的list类型,而非单个ggplot S3对象,因此无法直接支持+语法的图层叠加操作。
正确提取方法
核心是从长度为1的结果列表中取出内部存储的ggplot对象即可,两种常用写法:
方法1:提取后取列表首个元素
pull()得到列表后,用[[或者purrr的pluck()取出第一个元素:
library(tidyverse) # 定义绘图函数 plot <- function(df, title){ df %>% ggplot(aes(class)) + geom_bar() + labs(title = title) } plots <- mpg %>% group_by(manufacturer) %>% nest() %>% # 修正原map写法的取值bug,用pmap按行传参 mutate(plots= pmap(list(data, manufacturer), ~plot(..1, ..2))) # 提取nissan对应的ggplot对象 nissan <- plots %>% filter(manufacturer == "nissan") %>% pull(plots) %>% pluck(1) # 等价于 `[[`(1) # 可正常叠加调整图层 nissan + labs(title = "Nissan")
方法2:直接在管道中用pluck定位
不需要先pull再提取,直接定位到对应行对应列的列表元素:
nissan <- plots %>% filter(manufacturer == "nissan") %>% # 第一个参数为列名,第二个参数为列表内元素的位置 pluck("plots", 1)
额外说明:原代码中
map(.x=data, ~plot(.x, manufacturer))的写法存在取值错误风险:map仅迭代data列,不会按行匹配对应行的manufacturer值,会导致所有图表标题取值异常,必须用pmap支持多列按行传参,才能保证每个子图的标题和数据匹配。
内容的提问来源于stack exchange,提问作者Vibramat
相关产品推荐
相关产品推荐

