如何在ggplot多面图中为不同子图自适应添加NBER衰退阴影(消除无数据区域的多余阴影)
如何在ggplot多面图中为不同子图自适应添加NBER衰退阴影(消除无数据区域的多余阴影)
这个问题我做金融时间序列可视化时也碰到过——直接加衰退阴影的话,会把所有衰退期都套在每个子图里,哪怕某只股票在那段时间根本没有数据,就像你提到的Microsoft图里的空白阴影区域。咱们只要给衰退数据做个「适配裁剪」,让它只在每个股票的实际数据区间内显示就行,具体操作如下:
第一步:计算每个股票的时间范围
首先得明确每只股票数据的起止日期,这样才能判断哪些衰退期需要裁剪:
library(tidyverse) # 统计每个股票的时间边界 stock_time_ranges <- final_df %>% group_by(stock) %>% summarize(min_date = min(date), max_date = max(date)) %>% ungroup()
第二步:把衰退期适配到每个股票的时间范围
接下来把衰退数据和每个股票的时间范围做组合,然后裁剪每个衰退期,只保留和股票数据重叠的部分:
# 处理衰退数据,让它适配每个股票的时间区间 adapted_nber <- crossing(stock_time_ranges, nber_date) %>% # 计算实际要显示的阴影边界:取衰退起始和股票起始的较大值,衰退结束和股票结束的较小值 mutate( xmin = pmax(Start, min_date), xmax = pmin(End, max_date) ) %>% # 过滤掉完全不重叠的衰退期(这种情况不需要画阴影) filter(xmin < xmax) %>% # 保留绘图需要的列 select(stock, xmin, xmax)
第三步:用处理后的阴影数据绘图
现在用适配好的adapted_nber来画阴影,记得把stock加入到aes里,让ggplot自动对应每个子图的阴影:
p1 <- final_df %>% ggplot(aes(x = date, y = close)) + geom_line() + # 加入stock到aes,确保阴影和对应子图匹配 geom_rect(data = adapted_nber, aes(xmin = xmin, xmax = xmax, ymin = -Inf, ymax = Inf, group = stock), alpha = 0.2, inherit.aes = FALSE) + facet_wrap(~stock, scales = "free") p1
这样处理后,Microsoft的子图里只会显示和它数据时间重叠的衰退阴影,那些超出数据范围的空白阴影就消失了;而Apple的子图依然会完整显示所有和它数据重叠的衰退期,完全符合你的需求~
备注:内容来源于stack exchange,提问作者Raul Guarini Riva
相关产品推荐
相关产品推荐

