在for循环中使用is.nan()<-0导致向量所有值被置0的问题
问题原因与解决方法
你的代码里RECALL[is.nan(RECALL[i])] <- 0这行逻辑有误,导致整个RECALL向量被错误赋值为0。
错误原因
当RECALL[i]是NaN时,is.nan(RECALL[i])返回单个TRUE值。在R中,用长度为1的逻辑值给向量索引时,这个逻辑值会被循环扩展到整个向量的长度——相当于你执行了RECALL[rep(TRUE, NUM_CALCS)] <- 0,直接把所有元素都设为0。哪怕后续循环给RECALL[i]重新赋值计算结果,之前的元素已经被改成0了,最终整个向量就全是0。
正确写法
方法1:用if语句判断当前元素
这是最直观的写法,只修改当前循环的RECALL[i]位置:
NUM_CALCS <- 1000 FALSE_NEG <- vector("numeric", NUM_CALCS) TRUE_POS <- vector("numeric", NUM_CALCS) RECALL <- vector("numeric", NUM_CALCS) for (i in 1:NUM_CALCS) { # 计算TRUE_POS[i] # 计算FALSE_NEG[i] RECALL[i] <- TRUE_POS[i] / (TRUE_POS[i] + FALSE_NEG[i]) if (is.nan(RECALL[i])) { RECALL[i] <- 0 } # 后续使用RECALL[i]的计算 }
方法2:用ifelse直接赋值
可以把计算和判断合并成一行,避免临时变量:
NUM_CALCS <- 1000 FALSE_NEG <- vector("numeric", NUM_CALCS) TRUE_POS <- vector("numeric", NUM_CALCS) RECALL <- vector("numeric", NUM_CALCS) for (i in 1:NUM_CALCS) { # 计算TRUE_POS[i] # 计算FALSE_NEG[i] RECALL[i] <- ifelse( is.nan(TRUE_POS[i] / (TRUE_POS[i] + FALSE_NEG[i])), 0, TRUE_POS[i] / (TRUE_POS[i] + FALSE_NEG[i]) ) # 后续使用RECALL[i]的计算 }
如果不想重复计算除法,也可以先存临时值:
for (i in 1:NUM_CALCS) { # 计算TRUE_POS[i] # 计算FALSE_NEG[i] temp_val <- TRUE_POS[i] / (TRUE_POS[i] + FALSE_NEG[i]) RECALL[i] <- ifelse(is.nan(temp_val), 0, temp_val) # 后续使用RECALL[i]的计算 }
方法3:用replace函数
replace函数可以针对单个值做替换:
for (i in 1:NUM_CALCS) { # 计算TRUE_POS[i] # 计算FALSE_NEG[i] RECALL[i] <- TRUE_POS[i] / (TRUE_POS[i] + FALSE_NEG[i]) RECALL[i] <- replace(RECALL[i], is.nan(RECALL[i]), 0) # 后续使用RECALL[i]的计算 }
这几种方法都只会修改当前循环的RECALL[i]元素,不会影响其他位置的值,既能在循环内完成NaN替换,也能保留正常计算的非零值。
内容的提问来源于stack exchange,提问作者CraigS
相关产品推荐
相关产品推荐

