使用data.table更新观测值过少的BMstratum分层类别问题
问题说明
本问题在r2evans回答后已编辑
示例数据
使用R的data.table包处理示例数据,定义关注变量、观测值统计变量及适配分层变量,生成数据并按BMstratum统计各变量非缺失观测值数量,初始化适配分层与原分层一致。
分层更新需求
针对adapted_BMstratum中的每个变量,手动调整:当A/B/C变量在对应分层的观测值少于2个时,按规则修改分层值(如1110分层观测值不足则改为1120等),并更新观测值统计。
当前问题
现有循环代码未得到预期结果,且出现'length(x) = 8 > 1' in coercion to 'logical(1)'警告;1100和1140分层需保留,后续将单独添加规则处理。
期望结果
得到符合规则的适配分层及正确观测值统计,例如B_adapted_BMstratum因1110、1120、1130分层未全部满足至少2个观测值,需统一调整为1120等。
解决方案
1. 构造示例数据(模拟业务场景)
library(data.table) set.seed(123) dt <- data.table( BMstratum = rep(c(1100, 1110, 1120, 1130, 1140), c(5, 1, 3, 1, 4)), A = sample(c(NA, 1:5), size = 14, replace = TRUE), B = sample(c(NA, 1:5), size = 14, replace = TRUE), C = sample(c(NA, 1:5), size = 14, replace = TRUE) ) # 初始化适配分层,与原分层完全一致 dt[, `:=`( A_adapted_BMstratum = BMstratum, B_adapted_BMstratum = BMstratum, C_adapted_BMstratum = BMstratum )] # 按原分层统计各变量非缺失观测数 stat_dt <- dt[, .( A_n = sum(!is.na(A)), B_n = sum(!is.na(B)), C_n = sum(!is.na(C)) ), by = BMstratum]
2. 修正分层调整逻辑(解决警告+实现需求)
# 排除无需调整的分层(1100、1140) target_strata <- setdiff(unique(dt$BMstratum), c(1100, 1140)) # 遍历每个关注变量处理适配分层 for (var in c("A", "B", "C")) { # 提取当前变量的分层统计数据 var_stat <- stat_dt[, .(BMstratum, n = get(paste0(var, "_n")))] # 筛选出观测数不足2的分层 adjust_strata <- var_stat[n < 2, BMstratum] # 对目标分层中需调整的部分,统一修改为1120(可按需替换规则) dt[ get(paste0(var, "_adapted_BMstratum")) %in% adjust_strata & get(paste0(var, "_adapted_BMstratum")) %in% target_strata, (paste0(var, "_adapted_BMstratum")) := 1120 ] # 更新当前变量的适配分层统计 stat_dt <- dt[, .( A_n = sum(!is.na(A)), B_n = sum(!is.na(B)), C_n = sum(!is.na(C)) ), by = get(paste0(var, "_adapted_BMstratum"))][ , setnames(.SD, "get", "BMstratum") ] } # 查看最终结果 print(dt) print(stat_dt)
3. 关键说明
- 原警告是因为循环中直接使用长度大于1的逻辑向量作为判断条件(如
dt$A_n < 2),导致R无法将其强制转为单个逻辑值。上述代码通过先按分层统计、再定位需调整分层的方式避免了这个问题。 - 代码中通过
setdiff排除了1100和1140分层,后续可直接在循环外添加针对这两个分层的单独处理规则。 - 示例中统一将需调整的分层改为1120,可根据实际业务规则修改目标分层值。
内容的提问来源于stack exchange,提问作者Tom
相关产品推荐
相关产品推荐

