R语言筛选数据框中至少4个非NA违约率的账户ID
问题说明
现有包含账户ID、五年期违约率(Def)两个字段的数据框,每个ID固定对应5条违约率记录,字段中存在大量缺失值(NA)。
可通过以下R代码生成测试数据:
ID = rep(1:50, each = 5) def = rnorm(n=250, mean=0.5, sd=0.2) ind = which(def %in% sample(def, 100)) def[ind] = NA df = data.frame(ID = ID, Def = def)
生成的测试数据前20行示例:
> head(df, 20) ID Def 1 1 0.39506938 2 1 NA 3 1 0.42946603 4 1 NA 5 1 NA 6 2 0.45125199 7 2 0.40519126 8 2 NA 9 2 0.65082718 10 2 NA 11 3 NA 12 3 0.46132736 13 3 0.06324983 14 3 0.72630862 15 3 0.63996092 16 4 0.72093890 17 4 NA 18 4 NA 19 4 0.61471461 20 4 0.51788498
需求:筛选并输出5条违约率记录中至少4条为非NA值的对应ID编号。
实现方案
以下提供3种R语言常用实现方式,可根据自己常用的工具链选择:
- 基础R实现(无需加载第三方包)
# 按ID分组统计每个ID下Def字段的非缺失值数量 non_na_stat <- aggregate( Def ~ ID, data = df, FUN = function(x) sum(!is.na(x)), na.action = NULL # 避免自动剔除带NA的行导致统计错误 ) # 提取非缺失值数量≥4的ID target_id <- non_na_stat$ID[non_na_stat$Def >= 4]
- dplyr实现(tidyverse工作流常用)
library(dplyr) target_id <- df %>% group_by(ID) %>% summarise(non_na_cnt = sum(!is.na(Def)), .groups = "drop") %>% filter(non_na_cnt >= 4) %>% pull(ID)
- data.table实现(大数据量下性能最优)
library(data.table) setDT(df) target_id <- df[, .(non_na_cnt = sum(!is.na(Def))), by = ID][non_na_cnt >= 4, ID]
注:原测试数据生成代码中
ind = which(def %in% sample(def, 100))的写法在生成的def值有重复时,会将重复值对应的位置一并设为NA,最终NA数量可能不等于100。如果需要精准随机抽取100个位置设为NA,可替换为ind = sample(1:250, 100)。
内容的提问来源于stack exchange,提问作者Saïd Maanan
相关产品推荐
相关产品推荐

