如何用data.table语法结合ifelse按分组计算满足NA占比条件的均值
问题描述
我编写的data.table代码原本运行正常,但想要加入条件判断按分组计算均值时无法得到正确结果。我的核心需求是:按Place和Year分组计算变量均值,仅当分组内的NA占比≤25%时计算有效均值,否则返回NA。
可复现示例代码
set.seed(1645) Place <- c(rep("Copenhagen",7),rep("Berlin",11),rep("Roma",12)) Year <- c(rep("2020",4),rep("2021",3),rep("2020",6),rep("2021",5),rep("2019",4),rep("2020",4),rep("2021",4)) Value1 <- c(runif(3),NA,runif(8),NA,runif(9),NA,runif(7)) Value2 <- c(runif(4),NA,runif(2),runif(6),NA,NA,runif(11),NA,NA,runif(2)) df <- data.frame(Place,Year,Value1,Value2)
现有代码
无判断条件的正常运行版本
library(data.table) setDT(df) df_means <- df[,.(Value1_mean = mean(Value1),Value2_mean = mean(Value2)), by = .(Place,Year)]
加入条件后不符合预期的版本
df_means2 <- df[,.(Value1_mean = ifelse(sum(is.na(Value1))/length(Value1)>=0.25,NA,mean(Value1,na.rm=TRUE)), Value2_mean = ifelse(sum(is.na(Value2))/length(Value2)>=0.25,NA,mean(Value2,na.rm=TRUE))), by = .(Place,Year)]
解决方案
你的代码存在两个问题:
- 判断条件符号写反:需求是NA占比≤25%时计算均值,也就是仅当占比超过25%时才返回NA,原代码里
>=0.25的判断会把刚好等于25%的符合条件的情况也判定为返回NA,不符合需求 - 向量化
ifelse在这里没必要使用,分组后每组的判断条件是长度为1的逻辑值,直接使用if...else结构更符合语义也更高效,同时可以避免向量化函数的隐式类型转换问题
修正后代码
setDT(df) df_means2 <- df[, .( Value1_mean = if (sum(is.na(Value1))/.N <= 0.25) mean(Value1, na.rm = TRUE) else NA_real_, Value2_mean = if (sum(is.na(Value2))/.N <= 0.25) mean(Value2, na.rm = TRUE) else NA_real_ ), by = .(Place, Year)]
这里用.N直接取分组内的观测数,比length(Value1)写法更简洁,同时用NA_real_保证返回值类型和数值均值一致,避免类型转换异常。
运行结果
> df_means2 Place Year Value1_mean Value2_mean 1: Copenhagen 2020 0.5145925 0.5678063 2: Copenhagen 2021 0.5942537 NA 3: Berlin 2020 0.4783384 0.3449264 4: Berlin 2021 0.5675098 NA 5: Roma 2019 0.6373937 0.6888995 6: Roma 2020 0.3668729 0.6842431 7: Roma 2021 0.3663229 NA
完全符合预期需求。
内容的提问来源于stack exchange,提问作者Mata
相关产品推荐
相关产品推荐

