如何在R的dplyr中对同一列执行lag操作?代码问题求解
问题:dplyr中mutate结合lag操作未得到预期结果
尝试在R的dplyr中使用mutate对同一列执行lag操作,但运行代码后未得到预期结果,以下是详细信息:
错误运行结果
> dataFill # A tibble: 6 x 4 Name Code nameCnt nameCntMult <chr> <dbl> <int> <dbl> 1 R 0 1 1 2 R 0 2 2 3 T 0 1 1 4 R 0 3 3 5 N 1 1 NA 6 N 1 2 2
期望结果
| Name | Code | nameCnt | nameCntMult |
|---|---|---|---|
| R | 0 | 1 | 1 |
| R | 0 | 2 | 2 |
| T | 0 | 1 | 1 |
| R | 0 | 3 | 3 |
| N | 1 | 1 | 3 |
| N | 1 | 2 | 3 |
可复现代码
library(dplyr) data <- data.frame( Name = c("R","R","T","R","N","N"), Code = c(0,0,0,0,1,1) ) dataFill <- data %>% group_by(Name, Code) %>% mutate(nameCnt = row_number()) %>% mutate(nameCntMult = nameCnt * 2) %>% mutate(nameCntMult = ifelse(Code == 0, nameCnt, lag(nameCntMult))) %>% ungroup() dataFill
问题原因
你的代码中使用group_by(Name, Code)分组后,lag(nameCntMult)是在分组内部执行的。对于Name="N", Code=1这个独立分组,第一行没有前一行数据所以返回NA;第二行的lag只能取到同一分组内第一行的NA,最终得到错误结果。而你实际需要的是全局范围内的lag,即取整个数据框中前一行的nameCntMult值,而非分组内的前一行。
解决方案
先完成nameCnt的分组计算,取消分组后再处理nameCntMult的填充逻辑,用tidyr::fill函数向下填充NA值更简洁高效:
library(dplyr) library(tidyr) data <- data.frame( Name = c("R","R","T","R","N","N"), Code = c(0,0,0,0,1,1) ) dataFill <- data %>% group_by(Name, Code) %>% mutate(nameCnt = row_number()) %>% ungroup() %>% # 先给Code=0的行赋值,Code=1的行设为NA mutate(nameCntMult = ifelse(Code == 0, nameCnt, NA)) %>% # 向下填充NA值,继承前一个非NA的nameCntMult fill(nameCntMult, .direction = "down") dataFill
运行后得到的结果与期望一致:
# A tibble: 6 × 4 Name Code nameCnt nameCntMult <chr> <dbl> <int> <int> 1 R 0 1 1 2 R 0 2 2 3 T 0 1 1 4 R 0 3 3 5 N 1 1 3 6 N 1 2 3
内容的提问来源于stack exchange,提问作者Village.Idyot
相关产品推荐
相关产品推荐

