R语言使用dplyr包lag函数时如何忽略NA取最近非缺失值
dplyr中lag()跳过NA取最近上一个非NA值的实现方法
原生dplyr::lag()没有内置na.rm参数实现跳过NA向前查找最近非缺失值的逻辑,不需要修改lag函数本身,只要先对需要lag的列做向前末次非NA值填充,再正常调用lag计算即可。
错误场景复现
先构造测试数据,复现错误计算结果:
library(dplyr) df <- tibble( Value1 = c(NA, 13, 6, 6, 5), Value2 = c(2, 3, NA, 4, 4) ) # 直接调用lag得到错误结果 df %>% mutate(NewValue_wrong = Value1 - lag(Value2))
运行输出和给出的错误示例完全一致:
- 第四行NewValue返回NA,原因是lag直接取了第三行Value2的NA值参与计算,没有继续向上查找非NA值。
正确实现方案
用tidyr包的fill()函数即可快速完成向前非NA值填充,.direction = "down"参数代表从上到下(向前)用最近的非NA值填充缺失位置,填充后再做lag差运算就能得到正确结果:
library(tidyr) df %>% # 对Value2做向前非NA填充 fill(Value2, .direction = "down") %>% # 正常lag计算 mutate(NewValue_correct = Value1 - lag(Value2))
运行结果完全匹配期望输出:
| Value1 | Value2 | NewValue_correct |
|---|---|---|
| NA | 2 | NA |
| 13 | 3 | 11 |
| 6 | 3 | 3 |
| 6 | 4 | 3 |
| 5 | 4 | 1 |
如果需要保留原列中Value2的NA值不被修改,可以先复制一列做填充计算,算完删除临时列即可:
df %>% mutate(temp_fill = Value2) %>% fill(temp_fill, .direction = "down") %>% mutate(NewValue_correct = Value1 - lag(temp_fill)) %>% select(-temp_fill)
不想额外加载tidyr的话,也可以用base R实现向前填充逻辑,核心是利用cumsum和分组索引匹配最近非NA值,再做lag计算即可,效果完全一致。
内容的提问来源于stack exchange,提问作者Jennifer Weller
相关产品推荐
相关产品推荐

