我的数据框看起来像这样:
x1 <- c("a", "c", "f", "j")
x2 <- c("b", "c", "g", "k")
x3 <- c("b", "d", "h", NA)
x4 <- c("a", "e", "i", NA)
df <- data.frame(x1, x2, x3, x4, stringsAsFactors=F)
df
x1 x2 x3 x4
1 a b b a
2 c c d e
3 f g h i
4 j k <NA> <NA>
Run Code Online (Sandbox Code Playgroud)
现在我有一个任意的向量:
vec <- c("a", "i", "s", "t", "z")
Run Code Online (Sandbox Code Playgroud)
我想将矢量值与数据帧中的每一行进行比较,并创建一个额外的列,指示是否至少找到一个矢量值.
生成的数据框应如下所示:
x1 x2 x3 x4 valueFound
1 a b b a 1
2 c c d e 0
3 f g h i 1
4 j k <NA> <NA> 0
Run Code Online (Sandbox Code Playgroud)
我想在没有循环的情况下这样做.非常感谢您的支持!
拉米
这将比apply基于解决方案更快(尽管它是神秘的构造):
as.numeric(rowSums(`dim<-`(as.matrix(df) %in% vec, dim(df))) >= 1)
[1] 1 0 1 0
Run Code Online (Sandbox Code Playgroud)
在这里,我们可以组成一些更大的数据来测试....这些基准测试是在100k行上.
set.seed(1)
nrow <- 100000
ncol <- 10
vec <- c("a", "i", "s", "t", "z")
df <- data.frame(matrix(sample(c(letters, NA), nrow * ncol, TRUE),
nrow = nrow, ncol = ncol), stringsAsFactors = FALSE)
Run Code Online (Sandbox Code Playgroud)
以下是我们目前采用的方法:
AM <- function() as.numeric(rowSums(`dim<-`(as.matrix(df) %in% vec, dim(df))) >= 1)
NR1 <- function() {
apply(df,1,function(x){
if(any(x %in% vec)){
1
} else {
0
}
})
}
NR2 <- function() apply(df, 1, function(x) any(x %in% vec) + 0)
NR3 <- function() apply(df, 1, function(x) as.numeric(any(x %in% vec)))
NR4 <- function() apply(df, 1, function(x) any(x %in% vec) %/% TRUE)
NR5 <- function() apply(df, 1, function(x) cumprod(any(x %in% vec)))
RS1 <- function() as.numeric(grepl(paste(vec, collapse="|"), do.call(paste, df)))
RS2 <- function() as.numeric(seq(nrow(df)) %in% row(df)[unlist(df) %in% vec])
Run Code Online (Sandbox Code Playgroud)
我怀疑NR功能会慢一点:
system.time(NR1()) # Other NR functions are about the same
# user system elapsed
# 1.172 0.000 1.196
Run Code Online (Sandbox Code Playgroud)
同样,理查德的第二种方法:
system.time(RS2())
# user system elapsed
# 0.918 0.000 0.932
Run Code Online (Sandbox Code Playgroud)
在grepl这个rowSum功能是留给基准:
library(microbenchmark)
microbenchmark(AM(), RS1())
# Unit: milliseconds
# expr min lq mean median uq max neval
# AM() 65.75296 67.2527 92.03043 84.58111 102.3199 234.6114 100
# RS1() 253.57360 256.6148 266.89640 260.18038 264.1531 385.6525 100
Run Code Online (Sandbox Code Playgroud)
这是一种方法:
df$valueFound <- apply(df,1,function(x){
if(any(x %in% vec)){
1
} else {
0
}
})
##
> df
x1 x2 x3 x4 valueFound
1 a b b a 1
2 c c d e 0
3 f g h i 1
4 j k <NA> <NA> 0
Run Code Online (Sandbox Code Playgroud)
感谢@David Arenburg和@CathG提供了一些更简洁的方法:
apply(df, 1, function(x) any(x %in% vec) + 0)apply(df, 1, function(x) as.numeric(any(x %in% vec)))只是为了好玩,还有其他一些有趣的变种:
apply(df, 1, function(x) any(x %in% vec) %/% TRUE)apply(df, 1, function(x) cumprod(any(x %in% vec)))由于您不想要循环,因此您可以发挥创意并将列逐行粘贴在一起,然后grepl将其与vec
> as.numeric(grepl(paste(vec, collapse="|"), do.call(paste, df)))
[1] 1 0 1 0
Run Code Online (Sandbox Code Playgroud)
这是将行与未列出的数据框进行比较的第二个选项
> as.numeric(seq(nrow(df)) %in% row(df)[unlist(df) %in% vec])
[1] 1 0 1 0
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
1091 次 |
| 最近记录: |