如何在R长数据框中添加参与者Timer非NA值计数并解决合并错误?
问题描述
我正在尝试在R的长数据框中为每个参与者添加一个计数变量。每个参与者有数百条观测值,我希望为每个参与者添加一次其Timer列非NA值的计数,其余单元格留为NA。使用dplyr计算时遇到两个问题:
- 结果同时统计了TRUE(条件满足)和FALSE(条件不满足)的数量,而我只需要TRUE对应的计数;
- 将计数结果添加回原数据集时,因行数不匹配出现替换错误。
当前代码:
dfl$Ntimer <- NA # 生成空的NA列 Ntimer <- dfl %>% group_by(participant) %>% count((!is.na(Timer))) Ntimer dfl$Ntimer <- Ntimer
Ntimer输出:
participant (!is.na(Timer)) n 300: LY9 TRUE 60 301: LYJ4 FALSE 344 302: LYJ4 TRUE 35 303: LYJ5 FALSE 336 304: LYJ5 TRUE 21
报错信息:
Error in `$<-.data.frame`(`*tmp*`, Ntimer, value = list(participant = c("LYN9", : replacement has 304 rows, data has 66619
解决方案
1. 只保留Timer非NA值的计数
不用count()同时统计两种情况,直接在分组后计算非NA值的总和,每个参与者只会得到一行结果:
Ntimer <- dfl %>% group_by(participant) %>% summarise(Ntimer = sum(!is.na(Timer)))
sum(!is.na(Timer))会把逻辑值TRUE转为1、FALSE转为0,求和后就是每个参与者Timer列非NA值的总数,自动过滤了FALSE对应的行。
2. 解决行数不匹配问题,合并回原数据
直接赋值会因为行数差异报错,用left_join()关联统计结果和原数据,再按需设置NA:
dfl <- dfl %>% left_join(Ntimer, by = "participant") %>% # 仅保留每个参与者的第一行计数,其余行设为NA group_by(participant) %>% mutate(Ntimer = ifelse(row_number() == 1, Ntimer, NA)) %>% ungroup()
如果需要每个参与者的所有行都显示计数,去掉后面的mutate和分组相关代码即可。
一步完成的简化写法
可以把统计和合并整合为一个流程,更高效:
dfl <- dfl %>% group_by(participant) %>% mutate( # 计算每个参与者的Timer非NA总数 total_non_na = sum(!is.na(Timer)), # 仅第一行保留总数,其余设为NA Ntimer = ifelse(row_number() == 1, total_non_na, NA) ) %>% select(-total_non_na) %>% # 删除临时计算列 ungroup()
内容的提问来源于stack exchange,提问作者Jasmine
相关产品推荐
相关产品推荐

