2017-03-22 16 views
1

所以我有一个数据帧,有一些行有NA值。我想检测一行是否有NA值,如果该行不是NA,则在新列中写出。所以我做了一个标准的双循环来解决它。我的问题是,我可以通过内置R功能更有效吗?我的代码工作,但如果我有一个更大的数据帧这将是乏味做这个如何使用R中的内置函数使代码更有效(for循环)?

我的代码:

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" 
     } 
    } 
} 
+1

'测试$ NA < - C( “否NA值”, “NA值”)[1个+ as.integer(申请(is.na(测试), 1,any))]' – jogo

回答

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是预先定义d在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)) 
+1

谢谢大家!但是这条线是做什么的?[1 + apply 我得到应用部分,但不是+1 – arezaie

+1

@arezaie'as.integer(FALSE)'为0,'as.integer(TRUE)'为1. R中的索引必须以1开头(用于索引矢量'c(“无NA值”,“NA值”))。 – jogo

+0

谢谢! Appriciate帮助/课程! – arezaie

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 

请注意,我改名为你NAnav以避免碰撞na,其在R.

特殊的意义
+0

'ifelse(rowSums(is.na(df))> 0,“NA value”,“No NA value”) –

+0

您可以一步完成iit – akrun

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 
另一种选择210

或用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"