R 如果其他变量为NA,则设置新变量NA
我想在我的数据框中添加一个新变量(N_notNAs),它定义了其他变量是否为NAR 如果其他变量为NA,则设置新变量NA,r,R,我想在我的数据框中添加一个新变量(N_notNAs),它定义了其他变量是否为NA x y z N_notNAs 2 3 NA NA NA 1 3 NA 2 3 5 1 4 4 3 1 不确定为什么这是您想要的输出,但实现这一点的一种可能方法是将每行的NA相加,并将其放在NA的幂上-这样,NA^0将返回1,其他所有内容都将变为NA NA^rowSums(is.na(df)) # [1] NA NA 1 1 另一个选项是Reduce N
x y z N_notNAs
2 3 NA NA
NA 1 3 NA
2 3 5 1
4 4 3 1
不确定为什么这是您想要的输出,但实现这一点的一种可能方法是将每行的
NA
相加,并将其放在NA
的幂上-这样,NA^0将返回1,其他所有内容都将变为NA
NA^rowSums(is.na(df))
# [1] NA NA 1 1
另一个选项是
Reduce
NA^Reduce(`|`, lapply(df1, is.na))
#[1] NA NA 1 1
与@davids相比,我更喜欢这个选项,因为它更有表现力,即代码更能显示所做的事情
ifelse(apply(is.na(df), 1, any), NA, 1)
例如,这里不需要记住NA^0等于1。或
rowSums(df) & rowSums(df, na.rm = T)
#[1] NA NA TRUE TRUE
@David Arenburg的解决方案非常巧妙,但这里还有一些其他的解决方案 前4个假设df的列是数字的,并使用相同的基本思想,而后3个不需要数字列。他们也使用一个共同的想法
ifelse
解决方案在字符计数方面最长,但可能更具可读性,也最不复杂
正如下面一位@alexis_laz所提到的,apply(…)
可以替换为!complete.cases(df)
在最后3个解决方案中,经过一些简化,我们将得到ifelse(complete.cases(df),1,NA)
,c(NA,1)[complete.cases(df)+1]
和匹配(complete.cases(df),TRUE)
有一个问题是,为什么要使用NA或1列。如果您想要一个逻辑正确/错误的结果,那么
应用(df,1,anyNA)
就可以了。免责声明:这里的一些基准答案会产生正确/错误向量,而不是NA或1向量
为了了解更多信息,这里是我的机器上3列data.frame(含1e6行)的基准测试:
Unit: milliseconds
expr min lq mean median uq max neval cld
alexis_laz(df) 12.87138 13.30044 15.46142 13.49258 13.80019 29.59228 10 a
akrun(df) 46.06203 48.31564 49.82198 49.94947 51.05219 53.91161 10 ab
GGrothendieck3(df) 55.42513 56.59798 69.37274 59.16803 64.44442 155.62797 10 ab
GGrothendieck4(df) 54.88489 58.08043 69.54111 58.63820 65.36838 149.21380 10 ab
GGrothendieck2(df) 60.26961 62.37184 97.93301 69.80034 158.39302 193.03562 10 bc
By989(df) 115.30531 118.81843 133.44343 123.17356 130.36815 223.22601 10 c
GGrothendieck1(df) 123.99504 128.61030 140.62055 132.31073 137.83856 220.33666 10 c
David(df) 131.42639 131.66415 143.03384 133.50082 136.29453 225.17487 10 c
GGrothendieck7(df) 1100.69319 1109.60500 1147.25668 1142.83955 1156.37090 1270.32547 10 d
GGrothendieck6(df) 1060.97719 1124.85486 1148.54833 1140.91949 1170.62952 1247.80220 10 d
GGrothendieck5(df) 1218.79235 1251.03109 1287.47851 1285.20543 1311.82753 1364.89158 10 e
PaulHiemstra(df) 1436.31149 1461.14340 1511.42476 1502.34413 1552.09517 1608.22418 10 f
对于1e5列和1e3行的df:
Unit: milliseconds
expr min lq mean median uq max neval cld
alexis_laz(df) 356.1987 360.8647 366.2464 364.4488 368.9666 391.5828 10 a
David(df) 1387.1657 1415.7325 1530.0748 1436.9192 1542.1830 1968.9455 10 a
akrun(df) 1773.5728 1800.9288 1880.9201 1868.3143 1965.7862 2018.0870 10 a
GGrothendieck5(df) 4891.3247 5385.9903 8206.9116 9065.2893 9890.5795 10284.7369 10 b
GGrothendieck6(df) 5034.4408 9089.9334 9099.5746 9785.7042 10221.1537 11905.3997 10 b
GGrothendieck7(df) 5142.7372 9635.2558 9711.4691 9861.5164 10524.7317 11651.6198 10 b
PaulHiemstra(df) 5326.8807 9959.3951 10079.1672 10175.4814 11048.6218 12659.1130 10 b
By989(df) 9941.5236 10015.6652 10090.2076 10067.7127 10123.5885 10300.4110 10 b
GGrothendieck2(df) 25715.5451 25840.3138 26686.3386 26453.6770 26982.5627 29689.6019 10 c
GGrothendieck3(df) 26065.7005 26343.5734 27112.4387 26470.7166 27267.7166 31374.5133 10 c
GGrothendieck4(df) 25911.6476 26179.3999 27121.3442 26361.2242 27335.2762 31941.6339 10 c
GGrothendieck1(df) 34979.3212 35162.3589 36254.1681 35685.4975 36470.3027 41130.0531 10 d
源代码:
David <-function(df) {
NA^rowSums(is.na(df))
}
By989 <- function(df) {
rowSums(df) & rowSums(df, na.rm = T)
}
PaulHiemstra <- function(df) {
ifelse(apply(is.na(df), 1, any), NA, 1)
}
akrun <- function(df) {
NA^Reduce(`|`, lapply(df, is.na))
}
GGrothendieck1 <- function(df) {
rowSums(0*df) + 1
}
GGrothendieck2 <- function(df) {
max.col(0*df) + 1
}
GGrothendieck3 <- function(df) {
do.call(pmin, 0*df) + 1
}
GGrothendieck4 <- function(df) {
do.call(pmax, 0*df) + 1
}
GGrothendieck5 <- function(df) {
ifelse(apply(df, 1, anyNA), NA, 1)
}
GGrothendieck6 <- function(df) {
c(NA, 1)[apply(df, 1, anyNA) + 1]
}
GGrothendieck7 <- function(df) {
match(apply(df, 1, anyNA), FALSE)
}
alexis_laz <- function(df) {
complete.cases(df)
}
set.seed(5)
n<-function(x) sample(c(1:5,NA),1e6,replace=TRUE)
df<-data.frame(A=n(),B=n(),C=n())
results<-microbenchmark(David(df),
By989(df),
PaulHiemstra(df),
akrun(df),
GGrothendieck1(df),
GGrothendieck2(df),
GGrothendieck3(df),
GGrothendieck4(df),
GGrothendieck5(df),
GGrothendieck6(df),
GGrothendieck7(df),
alexis_laz(df),
times=10)
print(results,order="mean")
DavidNA^rowSums(is.NA(df))
@DavidArenburg应该是一个答案。如果我想为一个子集这样做?假设我有另一个变量ID=1:4。我想对ID>2和变量y和z这样做。只需在这个表达式中子集df
。只要你保持它是一个data.frame
所有的方法都会工作,例如,像NA^rowSums(is.NA(df[df$ID>2,c(“y”,“z”)))
应该工作我已经这样尝试过了:is.NA(categories2[categories2$ID>100,categories2[,2:13]),但是我得到了>>无效的下标类型“list”+1!,虽然我发现代码有点晦涩。在我的回答中,我给出了一个稍微详细一点的解决方案,但更清楚地显示了所做的事情。这可能是NA^apply(df,1,anyNA)
youhavemyupvote:)。虽然这个解决方案比@david@989的答案更加模糊,但是在3列的1e6 df上,这个答案和david的答案(执行50次后的平均时间为160毫秒)之间没有真正的区别,^0
是确定的,任何数字^0都会变成1,我们可能会争论NA不是一个数字,但在R中,NA对于每个类都有一个版本,除了raw,这听起来是合乎逻辑的。。。(至少对我来说)添加到集合中,!complete.cases(df)
可以方便地创建输出。@alexis_laz,这也适用于David Arenburg的解决方案。您也可以在他的下方添加注释。没错,完成。可以对案例进行各种操作,以返回预期结果。一、 只是,因为你的回答比较彻底,所以在这里加了。(…和半幸运的{set.seed(2016);样本(c(“gabor”,“989”,“david”,“paul”,“akrun”),1)}
同意在何处发表评论:-))恭喜,这里是最快的版本,与G的do.看涨期权竞争。Grothendieck@989你是九号人物;-)@989个数字作为函数名很难,我将纠正拼写:p(使用更多列的更好基准测试)我想,在其他替代方法中,还有另一种方法可以使完整。cases
的工作是替换(NA_integer,complete.cases(df),1L)
,如果不是的话-仅仅是{ans=rep_len(NA_integer,nrow(df));ans[complete.cases(df)]=1L;ans}
为了避免一些胁迫和操作。@亚历克西斯·拉兹恭喜你,两种情况下更快的答案是yours@alexis_laz你应该发布一个答案。Tensibai你修改后的基准看起来比较现实。
David <-function(df) {
NA^rowSums(is.na(df))
}
By989 <- function(df) {
rowSums(df) & rowSums(df, na.rm = T)
}
PaulHiemstra <- function(df) {
ifelse(apply(is.na(df), 1, any), NA, 1)
}
akrun <- function(df) {
NA^Reduce(`|`, lapply(df, is.na))
}
GGrothendieck1 <- function(df) {
rowSums(0*df) + 1
}
GGrothendieck2 <- function(df) {
max.col(0*df) + 1
}
GGrothendieck3 <- function(df) {
do.call(pmin, 0*df) + 1
}
GGrothendieck4 <- function(df) {
do.call(pmax, 0*df) + 1
}
GGrothendieck5 <- function(df) {
ifelse(apply(df, 1, anyNA), NA, 1)
}
GGrothendieck6 <- function(df) {
c(NA, 1)[apply(df, 1, anyNA) + 1]
}
GGrothendieck7 <- function(df) {
match(apply(df, 1, anyNA), FALSE)
}
alexis_laz <- function(df) {
complete.cases(df)
}
set.seed(5)
n<-function(x) sample(c(1:5,NA),1e6,replace=TRUE)
df<-data.frame(A=n(),B=n(),C=n())
results<-microbenchmark(David(df),
By989(df),
PaulHiemstra(df),
akrun(df),
GGrothendieck1(df),
GGrothendieck2(df),
GGrothendieck3(df),
GGrothendieck4(df),
GGrothendieck5(df),
GGrothendieck6(df),
GGrothendieck7(df),
alexis_laz(df),
times=10)
print(results,order="mean")