【问题标题】:User-written function to replace NA by 0 by for loop not working in r用户编写的函数将 NA 替换为 0,for 循环在 r 中不起作用
【发布时间】:2021-08-09 07:58:45
【问题描述】:

[数据表] 如果列是数字,我已经编写了一个这样的函数来将 NA 替换为 0

fn.naremove <- function(data){ 
for (i in 1: length(data)){
if (class(data[[i]]) %in% c("numeric", "interger", "interger64")) {
  print(data[, names(data[, i]) := replace(data[, i], is.na(data[, i]), 0)])
} 
else {
 print(data)
}}}

我有一个如下所示的示例数据表

dt1<- data.table(C1= c(1, 5, 14, NA, 54), C2= c(9, NA, NA, 3, 42), C3= c(9, 7, 42, 87, NA))

如果我使用fn.naremove(dt1) 它返回错误

Error in `[.data.table`(data, , i) : 
j (the 2nd argument inside [...]) is a single symbol but column name 'i' is not found. 
Perhaps you intended DT[, ..i]. This difference to data.frame is deliberate and explained in FAQ 1.1.

如果我使用实际的列索引运行代码,它会顺利运行并返回我想要的列号 1 的结果:

dt1[, names(dt1[, 1]) := replace(dt1[, 1], is.na(dt1[, 1]), 0)]

  C1 C2 C3
1:  1  9  9
2:  5 NA  7
3: 14 NA 42
4:  0  3 87
5: 54 42 NA

如果我错过了我的功能或做错了什么,请告诉我。 提前致谢!!

【问题讨论】:

  • 为什么要在函数中打印?
  • 我搜索了stackoverflow,了解到如果你想让你的代码在里面工作,你需要把print()放到它上面。因为您将在 R 控制台中看到结果打印出来。

标签: r function for-loop if-statement data.table


【解决方案1】:

您可以使用replace

replace(dt1, is.na(dt1), 0)
#    C1 C2 C3
# 1:  1  9  9
# 2:  5  0  7
# 3: 14  0 42
# 4:  0  3 87
# 5: 54 42  0

function 周围有一个很好的 data.table 宇宙,我们可以扩展它以适应特定的类。

dt1 <- cbind(dt1, x=c("a", NA))  ## add a categorcal variable

library(data.table)
classes <- c("numeric", "interger", "interger64")  ## define sp. classes

fun <- function(DT) {
  for (j in names(DT)) {
    set(DT, which(is.na(DT[[j]]) & class(DT[[j]]) %in% classes), j, 0)
  }
}

fun(dt1)
dt1
#    C1 C2 C3    x
# 1:  1  9  9    a
# 2:  5  0  7 <NA>
# 3: 14  0 42    a
# 4:  0  3 87 <NA>
# 5: 54 42  0    a

仅替换已定义类的 NA。这应该是最有效的,因为没有复制。

【讨论】:

  • 感谢您的回答!也许我必须回到手动过滤分类列的方式,这会更容易!
  • @1darknight 查看更新,说明所需的班级选择。
【解决方案2】:

请注意,names(dt1[, 1]) 有效,但当您这样做时 -

i <- 1
names(dt1[, i])

它不起作用并返回错误

[.data.table(dt1, , i) 中的错误: j([...] 中的第二个参数)是单个符号,但未找到列名“i”。也许您打算使用 DT[, ..i]。与 data.frame 的这种差异是经过深思熟虑的,并在 FAQ 1.1 中进行了解释。

解决方案是使用..i,即names(dt1[, ..i])


其他选项是 -

fn.naremove <- function(data){ 
  for (i in 1: length(data)){
    if (class(data[[i]]) %in% c("numeric", "interger", "interger64")) {
      print(data[, names(data)[i] := replace(data[[i]], is.na(data[[i]]), 0)])
    } else {
      print(data)
    }}
}
fn.naremove(dt1)

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2020-04-23
    • 2021-07-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-07-08
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多