如何在ggplot2的geom_point()中高效复用已过滤的2012年gapminder数据?
优化Gapminder散点图代码:避免重复过滤年份数据
这个问题我太懂了——重复过滤同一个条件确实挺烦的,既冗余又浪费算力。你之前尝试的思路是对的:先把2012年的数据过滤出来再传给ggplot,但报错是因为图层里的filter()不知道该用哪个数据集。下面给你两种简洁高效的解决方案,不用额外创建新数据框,只需要一次过滤2012年的数据就能复用在所有图层里:
方法1:用.指代管道传递的已过滤数据
在ggplot的管道链里,.代表前一步传递过来的数据集(也就是我们已经过滤好的2012年数据)。只需要在图层的data参数里用. %>% filter(...)的形式,就能基于已过滤的数据进一步筛选:
# 先计算2012年亚洲人口中位数(用pull()简化代码) med_2012_pop <- gapminder %>% filter(year == 2012 & continent == "Asia") %>% pull(population) %>% median(na.rm = TRUE) # 一次过滤2012年数据,后续所有图层复用 gapminder %>% filter(year == 2012) %>% ggplot(aes(x=fertility, y=life_expectancy, color=continent)) + # 高亮亚洲人口超过中位数的点 geom_point(data = . %>% filter(continent == "Asia" & population > med_2012_pop), size=5, color="gray") + # 基础散点图层(直接用已过滤的2012年数据) geom_point() + # 高亮日本 geom_point(data = . %>% filter(country == "Japan"), size=1, color="black") + geom_label(x=1.8, y=84, label="Japan", color="black", size=3) + theme_minimal()
方法2:用cur_data()引用ggplot当前数据(ggplot2 3.3.0+适用)
如果你的ggplot2版本在3.3.0及以上,可以用cur_data()函数,它会直接返回ggplot正在使用的数据集,语法更直观:
gapminder %>% filter(year == 2012) %>% ggplot(aes(x=fertility, y=life_expectancy, color=continent)) + geom_point(data = cur_data() %>% filter(continent == "Asia" & population > med_2012_pop), size=5, color="gray") + geom_point() + geom_point(data = cur_data() %>% filter(country == "Japan"), size=1, color="black") + geom_label(x=1.8, y=84, label="Japan", color="black", size=3) + theme_minimal()
为什么之前的代码报错?
你之前尝试的filter(continent == "Asia" ...)没有指定数据源,R不知道要过滤哪个数据框。而上面两种方法明确告诉R:用的是已经过滤好的2012年数据,这样就不会出错了。
额外小优化
计算中位数的时候,用pull(population)比select(population) %>% .$population更简洁,代码可读性更高,建议日常使用~
内容的提问来源于stack exchange,提问作者Vivi
相关产品推荐
相关产品推荐

