如何按game分组标记DataFrame中possession值的行变更情况?
问题描述
我有如下结构的DataFrame:
| game | possession |
|---|---|
| A - B | A |
| A - B | A |
| A - B | A |
| A - B | B |
| A - B | A |
| C - D | D |
| C - D | D |
| C - D | C |
| C - D | C |
| C - D | D |
生成该数据的R代码:
library(tidyverse) df <- tibble( game = c("A - B", "A - B", "A - B", "A - B", "A - B", "C - D", "C - D", "C - D", "C - D", "C - D"), possession = c("A", "A", "A", "B", "A", "D", "D", "C", "C", "D") )
我想要添加第三列transit,用来标记possession列的值是否发生变更。尝试了以下代码,但结合group_by使用时无法正常工作:
df %>% group_by(game) %>% mutate(transit = ifelse(df$possession != dplyr::lag(df$possession), "yes", "no"))
期望得到的输出如下:
| game | possession | transit |
|---|---|---|
| A - B | A | NA |
| A - B | A | no |
| A - B | A | no |
| A - B | B | yes |
| A - B | A | yes |
| C - D | D | NA |
| C - D | D | no |
| C - D | C | yes |
| C - D | C | no |
| C - D | D | yes |
解决方案
你的代码问题出在使用df$possession直接引用原数据框的列,而非利用group_by后的分组上下文。在分组操作中,应直接使用列名,不需要df$前缀,且lag()会自动在每个分组内计算前一行的值。
修正代码(匹配期望输出)
df %>% group_by(game) %>% mutate(transit = case_when( is.na(lag(possession)) ~ NA_character_, possession != lag(possession) ~ "yes", TRUE ~ "no" )) %>% ungroup() # 可选,取消分组状态
简化版代码
如果不需要显式处理NA,也可以用ifelse:
df %>% group_by(game) %>% mutate(transit = ifelse(possession != lag(possession), "yes", "no"))
关键说明
- 移除
df$前缀后,dplyr会在每个game分组的子数据框中处理列,确保lag()只在当前分组内取前一行值 case_when可以清晰地将每个分组的第一行设为NA,后续行根据与前一行的对比结果返回"yes"或"no",完全匹配你的期望输出
内容的提问来源于stack exchange,提问作者Delopera
相关产品推荐
相关产品推荐

