Plotly中accumulate_by传~date的作用及相关技术疑问
关于Plotly累积折线动画中
accumulate_by函数的解析 让我一步步拆解这个函数,帮你搞清楚传入~date时的细节和整个逻辑:
1. 传入~date时,dat和var的具体取值
- 首先,
dat就是你传入的数据集——也就是经过filter(year > 2005, city %in% c("Abilene", "Bay Area"))处理后的txhousing子集,包含两个城市2005年后的房产数据。 - 而你传入的
~date是一个公式对象(不是直接的列名字符串),它会先被传入accumulate_by的var参数。接下来通过lazyeval::f_eval(var, dat),这个函数会把公式~date在dat的环境中求值,最终var会变成dat$date这个日期向量——也就是子集中所有的日期数据。
2. accumulate_by函数的完整工作流程
这个函数的核心是生成累积式的动画帧数据,步骤如下:
- 第一步:通过
lazyeval::f_eval把传入的公式(比如~date)转换成数据集中对应的列向量,拿到我们要按其累积的变量(这里是日期)。 - 第二步:调用
plotly:::getLevels(var)获取该变量的所有唯一值,并且按原有顺序排列(对于日期来说就是按时间先后排序),得到一个有序的唯一值列表lvls。 - 第三步:用
lapply遍历lvls的每个位置x(从1到总长度):- 筛选出
dat中var(日期)属于lvls[seq(1, x)]的所有行——也就是从第一个日期到第x个日期的所有历史数据。 - 给筛选出的子集新增一列
frame,值为当前的lvls[[x]](也就是当前累积到的日期)。
- 筛选出
- 第四步:用
dplyr::bind_rows把所有这些子集合并成一个大数据集,这个数据集就是动画的基础——每个frame对应到某个日期为止的全部累积数据,这样Plotly就能按帧播放出从最早日期逐步累积到最新日期的动画效果。
3. 关于plotly:::getLevels函数的说明
这个是Plotly包的内部未导出函数(所以用:::调用,而非公开的::),官方确实没有对外提供文档。它的核心作用是提取输入向量的所有唯一值,并且严格保留数据的固有顺序:
- 如果是因子,就按因子水平的顺序返回;
- 如果是日期、数值这类有序数据,就按自然顺序排序后返回;
- 这比普通的
unique()函数更适合时间序列动画,能保证累积的顺序不会乱。
内容的提问来源于stack exchange,提问作者Arseny Sokolov
相关产品推荐
相关产品推荐

