在R中使用循环将数据框中的NA替换为0

3
我想遍历数据框中的特定列,并使用循环将所有NA替换为0。
extract = read.csv("2013-09 Data extract.csv")
extract$Premium1[is.na(extract$Premium1)] <- 0
extract$Premium1

这段代码能为数据框 extract 中的 Premium1 列提供所需的结果,但我想循环遍历所有27列的保险费,所以我正在尝试以下代码:

extract = read.csv("2013-09 Data extract.csv")

for(i in 1:27) { 
  thispremium <- get(paste("extract$Premium", i, sep="")) 
  thispremium[is.na(thispremium)] <- 0
}

这提供了

Error in get(paste("extract$Premium", i, sep = "")) : 
  object 'extract$Premium1' not found

有没有想法是什么导致了这个错误?


1
get()不会解析字符串。也许可以这样写:get("extract")[[paste0("Premium",i)]],尽管它看起来很别扭。为什么你需要用get取'extract'呢?为什么不直接写成:extract[[paste0("Premium",i)]]呢? - IRTFM
请看以下答案:链接 - Tony Laidig
感谢您的观察,DWin。我现在正在使用 for(i in 1:27) { extract[[paste0("Premium", i)]][is.na(extract[[paste0("Premium", i)]])] <-0 } 这段代码,它可以给出所需的结果。 - Aaa
@user1886721 我不想替换数据框中的所有NA值;不过这是一篇有趣的阅读,谢谢。 - Aaa
2个回答

2
如何呢?
for (colname in names(extract))
  extract[[colname]][is.na(extract[[colname]])] <- 0

(甚至是extract[is.na(extract)] <- 0
或者,如果您不是对所有列都执行此操作(我想我误读了您的问题):
for(i in 1:27) { 
  colname <- paste0("Premium",i)
  extract[[colname]][is.na(extract[[colname]])] <- 0
}

或者,你实际上不需要知道这些列的数量:

premium <- grep("^Premium[0-9]*$",names(extract))
extract[premium][is.na(extract[premium])] <- 0

谢谢sds;是的,我只想修改特定的列。你和Dwin的解决方案都可以解决问题,但我发现Konrad的解决方案更优雅 :) - Aaa
我收到了这个错误信息:Warning message: In grep(names(extract), "^Premium") : argument 'pattern' has length > 1 and only the first element will be used。我不确定这个解决方案试图实现什么,但如果它是选择所有标题中带有“Premium”的列,那么我会对实施它感到担心,因为还有其他列(例如再保险的 ReasPremium1)我不想触及。 - Aaa
抱歉,修正了参数顺序。这个正则表达式选择以“Premium”开头并带有数字的列。 - sds

2

你是否需要使用循环是因为其他要求?因为即使没有循环也可以正常工作:

extract[is.na(extract)] <- 0

如果您只想替换某些列,请先选择这些列,执行替换操作,然后将这些列替换回原始集合:

first5 <- extract[, 1 : 5]
first5[is.na(first5)] <- 0
extract[, 1 : 5] <- first5

通常情况下,在R语言中应该尽量避免使用循环(尤其是在操作数据框时)。通常操作会自动向量化(如上所示)。当它们没有自动向量化时,可以使用apply函数族的函数。


谢谢Konrad。我在互联网上看到过这个解决方案,但在我的情况下,我希望仅从选定的一组列中删除NAs。 - Aaa
1
@Adriaan 当然可以。实际上,你应该使用变量而不是硬编码的绝对列。只需用列的(变量)名称替换我使用的范围即可。例如,使用类似于 c('Premium1', 'Premium3') 而不是 1:5 的内容。 - Konrad Rudolph
1
哇,太棒了!我现在使用的是 working <- extract[, c(paste0("Premium", 1:27))] working[is.na(working)] <- 0 extract[, c(paste0("Premium", 1:27)) ] <- working,它完美地解决了问题。谢谢! - Aaa
1
在这种情况下,甚至不需要 c(…)。直接使用 paste0("Premium", 1:27) 即可。 - Konrad Rudolph
谢谢Konrad。代码也可以缩短为extract[, paste0("Premium", 1:27)][is.na(extract[, paste0("Premium", 1:27)])] <- 0 - Aaa
显示剩余3条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接