在R中基于动物ID与采样日期清理特定Initials列NA行
解决方案:按动物-采样日期分组清理Initials列的NA行
需求梳理
针对每一组AnimalID + DateSampled:
- 当组内存在2个非NA值+2个NA值时,删除所有NA行
- 当组内全为NA值时,保留所有行
- 当组内存在**4个非NA值(两组采样人员各2行)**时,保留所有行
实现方案
方法1:使用dplyr(推荐,简洁高效)
利用分组计算组内非NA的数量,再根据条件筛选行:
library(dplyr) # 初始化示例数据(修正原数据的长度匹配问题) Data <- data.frame(matrix(ncol = 3, nrow = 24)) colnames(Data) <- c('AnimalID', 'DateSampled', 'Initials') Data$AnimalID <- c(1,1,1,1,2,2,2,2,3,3,3,3,4,4,4,4,5,5,5,5,6,6,6,6) Data$DateSampled <- as.Date(c("2021-10-13", "2021-10-13", "2021-10-13", "2021-10-13", "2021-10-27", "2021-10-27", "2021-10-27", "2021-10-27", "2021-11-10", "2021-11-10", "2021-11-10", "2021-11-10", "2021-11-24", "2021-11-24", "2021-11-24", "2021-11-24", "2021-12-01", "2021-12-01", "2021-12-01", "2021-12-01", "2021-12-05", "2021-12-05", "2021-12-05", "2021-12-05")) Data$Initials <- c("AB", "AB", NA, NA, "AB", "AB", "CD", "CD", "AB", "AB", NA, NA, "AB", "AB", "CD", "CD", "AB", "AB", NA, NA, NA, NA, NA, NA) # 核心处理逻辑 cleaned_data <- Data %>% group_by(AnimalID, DateSampled) %>% mutate( non_na_count = sum(!is.na(Initials)), all_na = all(is.na(Initials)) ) %>% filter( # 保留非NA行,或者全为NA时的所有行 !is.na(Initials) | all_na ) %>% select(-non_na_count, -all_na) %>% # 移除临时计算列 ungroup() # 查看结果 print(cleaned_data, n = Inf)
方法2:基础R实现(循环+条件向量)
如果不想依赖tidyverse包,用基础R分组循环处理:
# 初始化示例数据(同上) # ... 此处省略数据初始化代码,与上面一致 ... # 生成分组标识键 group_keys <- paste(Data$AnimalID, Data$DateSampled, sep = "_") unique_groups <- unique(group_keys) # 初始化行保留标记向量 keep_rows <- logical(nrow(Data)) # 遍历每个分组处理 for(g in unique_groups){ group_rows <- which(group_keys == g) group_initials <- Data$Initials[group_rows] non_na_count <- sum(!is.na(group_initials)) if(non_na_count == 2){ # 组内有2个非NA,仅保留非NA行 keep_rows[group_rows] <- !is.na(group_initials) } else if(non_na_count == 0){ # 组内全为NA,保留所有行 keep_rows[group_rows] <- TRUE } else { # 其他情况(如4个非NA),保留所有行 keep_rows[group_rows] <- TRUE } } # 筛选得到清理后的数据 cleaned_data_base <- Data[keep_rows, ] # 查看结果 print(cleaned_data_base, n = Inf)
输出结果
两种方法都会生成符合需求的输出:
# A tibble: 18 × 3 AnimalID DateSampled Initials <dbl> <date> <chr> 1 1 2021-10-13 AB 2 1 2021-10-13 AB 3 2 2021-10-27 AB 4 2 2021-10-27 AB 5 2 2021-10-27 CD 6 2 2021-10-27 CD 7 3 2021-11-10 AB 8 3 2021-11-10 AB 9 4 2021-11-24 AB 10 4 2021-11-24 AB 11 4 2021-11-24 CD 12 4 2021-11-24 CD 13 5 2021-12-01 AB 14 5 2021-12-01 AB 15 6 2021-12-05 NA 16 6 2021-12-05 NA 17 6 2021-12-05 NA 18 6 2021-12-05 NA
内容的提问来源于stack exchange,提问作者ruser123
相关产品推荐
相关产品推荐

