如何在R中使用内置函数使我的代码更有效(for循环)?

时间:2017-03-22 08:02:15

标签: r for-loop

所以我有一个数据帧,其中一些行具有NA值。我想检测一行是否具有NA值,如果该行是否为NA,则在新列中写出。所以我做了一个标准的双循环来解决它。我的问题是,我可以使用内置R函数更有效吗?我的代码可以工作,但如果我有一个更大的数据框,那么执行此操作将非常繁琐

我的代码:

for (j in 1:ncol(test)) {
    for (i in 1:nrow(test)) {
        if (is.na(test[i,j])) {
            test$NA[i] <- "NA value"
        }
        else {
            test$NA[i] <- "No NA value"
        }
    }
}

3 个答案:

答案 0 :(得分:2)

如果我正确读取了双循环,您希望将数据框中的每一行标记为NA value,如果NA在该行中至少出现一次,则标记为No NA value。您可以在此处使用一些基本R函数来执行此操作,包括rowSums()is.na()

df <- data.frame(v1=c(1,NA,2), v2=c(1,2,3), v3=c(1,2,NA))
df$nav[rowSums(is.na(df)) == 0] <- "No NA value"
df$nav[rowSums(is.na(df)) > 0] <- "NA value"
> df
  v1 v2 v3         nav
1  1  1  1 No NA value
2 NA  2  2    NA value
3  2  3 NA    NA value

请注意,我将您的NA列重命名为nav,以避免与na发生冲突,后者在R中具有特殊含义。

答案 1 :(得分:2)

您可以使用apply()

set.seed(42)
test <- matrix(sample(c(3:12, NA), 20, repl=TRUE), 5)
test <- as.data.frame(test)
test$`NA` <- c("No NA value", "NA value")[1 + apply(is.na(test), 1, any)]
test
#   V1 V2 V3 V4          NA
# 1 NA  8  8 NA    NA value
# 2 NA 11 10 NA    NA value
# 3  6  4 NA  4    NA value
# 4 12 10  5  8 No NA value
# 5 10 10  8  9 No NA value

命名新列“NA”并不是一个好主意,因为NA中预定了R。如果您不需要新列中的标签,则可以使用

test$NAindicator <- apply(is.na(test), 1, any)

您还可以将test保留为矩阵:

set.seed(42)
test <- matrix(sample(c(3:12, NA), 20, repl=TRUE), 5)
test <- cbind(test, apply(is.na(test), 1, any))
test
#      [,1] [,2] [,3] [,4] [,5]
# [1,]   NA    8    8   NA    1
# [2,]   NA   11   10   NA    1
# [3,]    6    4   NA    4    1
# [4,]   12   10    5    8    0
# [5,]   10   10    8    9    0

或者你可以把它放在一个列表中:

list(mat=test, NAindicator=apply(is.na(test), 1, any))

答案 2 :(得分:0)

以下是Reduce

的另一个选项
library(data.table)
setDT(test)[, NAV := c("No NA value", "NA value")[is.na(Reduce(`+`, .SD)) + 1]] 
test
#   V1 V2 V3 V4         NAV
#1: NA  8  8 NA    NA value
#2: NA 11 10 NA    NA value
#3:  6  4 NA  4    NA value
#4: 12 10  5  8 No NA value
#5: 10 10  8  9 No NA value

base R

test$NAV <- paste(sub("\\d+", "No NA", do.call(pmax, test)), "value")
test$NAV
#[1] "NA value"    "NA value"    "NA value"    "No NA value" "No NA value"