R语言嵌套for循环用case_when给数据框赋值返回NA问题
问题原因
你的代码核心问题是每次循环执行mutate()都会重写整个state_prob列,不会保留之前循环已经赋好的值:
- 每一轮
case_when运行时,只有3类行会被赋值:匹配当前i、j组合的行、x=0的行、x=1且y>=6的行 - 其余所有x=1且y<6、又不匹配当前i、j的行,会被直接赋值为NA,把前几轮循环给这些行算好的值全部覆盖
- 双层循环跑到最后一轮时,只有匹配最后一组i、j的行能拿到正确值,其余之前匹配过的x=1的行全被覆盖成NA,就出现了你看到的错误结果。
正确实现方案
完全不需要写双层for循环,R原生支持向量化的矩阵索引,一行代码就能完成匹配,效率远高于循环,也不会出现覆盖问题:
library(dplyr) df <- df %>% mutate( state_prob = case_when( x == 0 ~ 0, x == 1 & y >= 6 ~ 0, # 对x=1且y<6的行,用y+1作为行号、z作为列号,批量提取table对应位置的值 TRUE ~ table[cbind(y + 1, z)] ) )
代码原理说明:
cbind(y+1, z)会生成一个两列矩阵,每一行对应一条数据需要查询的table行号、列号- R中对table、matrix类对象传入这种两列索引矩阵时,会一次性返回每一组(行,列)坐标对应的数值,是原生的向量化操作,不需要逐行、逐组合循环。
如果你一定要保留循环的写法,需要先初始化state_prob列,每次循环只给未赋值的匹配行补值,不能全列重写(不推荐,效率极低),参考写法:
# 初始化列 df$state_prob <- NA_real_ # 循环仅填充匹配的组合值 for (i in 0:5) { for (j in 1:6) { match_row <- df$x == 1 & df$y == i & df$z == j & is.na(df$state_prob) df$state_prob[match_row] <- table[i+1, j] } } # 最后填充固定规则的0值 df <- df %>% mutate( state_prob = case_when( x == 0 ~ 0, x == 1 & y >=6 ~ 0, TRUE ~ state_prob ) )
内容的提问来源于stack exchange,提问作者antwan81
相关产品推荐
相关产品推荐

