我写了以下函数,它有效。但是,如果df1
有1700行,而df2
有70000行,则速度非常慢。反正有没有提高效率?
rowcheck <- function(df1, df2){
apply(df1, 1, function(x) any(apply(df2, 1, function(y) all(y==x))))
}
我写这个函数应用的一个例子是:我想检查df1中的每一行是否包含在df2中的一行:
df1=data.frame(a=c(1:3),b=c("a","b","c"))
df2=data.frame(a=c(1:6),b=rep(c("a","b","c"),2))
对于df1的每一行,我想检查它是否作为df2中的行包含。我想将函数返回为长度为nrow(df1)的逻辑向量。
感谢您的帮助。
答案 0 :(得分:11)
一种方法是将行粘贴在一起,并将它们与%in%
进行比较。结果是一个逻辑向量,长度为nrow(df1)
,如请求的那样。
do.call(paste0, df1) %in% do.call(paste0, df2)
# [1] TRUE TRUE TRUE
答案 1 :(得分:6)
尝试:
Filter(function(x) x > 0, which(duplicated(rbind(df2, df1))) - nrow(df2))
它会告诉您df1
中df2
中出现了哪些行号。如果你想要一个逻辑的原子向量,如Richard Scriven的答案,试试
duplicated(rbind(df2, df1))[-seq_len(nrow(df2))]
它也更快,因为它使用内部C函数duplicated
(我的是rowcheck2
)
> microbenchmark(rowcheck(df1, df2), rowcheck2(df1, df2))
Unit: milliseconds
expr min lq median uq max neval
rowcheck(df1, df2) 2.045210 2.169182 2.328296 3.539328 13.971517 100
rowcheck2(df1, df2) 1.046207 1.112395 1.243390 1.727921 7.442499 100
答案 2 :(得分:1)
只是想对这个问题给出两分钱。基于plyr的解决方案:
nrow(match_df(df2, df1))
..将针对df2(相对于所有列)检查df1的每一行,并给出df2中包含的df1的行数。
答案 3 :(得分:0)
基于 merge
的解决方案是:
# simulate data
options(stringsAsFactors = FALSE)
set.seed(1)
n1 <- 400L
n2 <- 1000L
df1 <- data.frame(a = sample.int(20L, n1, TRUE) ,
b = sample(letters, n1, TRUE))
df2 <- data.frame(a = sample.int(20L, n2, TRUE),
b = sample(letters, n2, TRUE))
df2 <- df2[!duplicated(df2), ]
# the new function
row_check_new <- function(x, y){
# are there columns in x that are not in y or vice versa?
if(length(union(colnames(x), colnames(y))) > length(colnames(x)))
return(logical(NROW(x)))
dum <- transform(x, row_id_dummy = 1:NROW(x))
dum$row_id_dummy %in% merge(dum, y)$row_id_dummy
}
# it yields the same
rowcheck <- function(df1, df2)
apply(df1, 1, function(x) any(apply(df2, 1, function(y) all(y==x))))
all.equal(rowcheck(df1, df2), row_check_new(df1, df2))
#R> [1] TRUE
# but is much faster
bench::mark(old = rowcheck(df1, df2), new = row_check_new(df1, df2))
#R> # A tibble: 2 x 13
#R> expression min median `itr/sec` mem_alloc `gc/sec` n_itr n_gc
#R> <bch:expr> <bch:tm> <bch:tm> <dbl> <bch:byt> <dbl> <int> <dbl>
#R> 1 old 322.56ms 327.26ms 3.06 11.4MB 18.3 2 12
#R> 2 new 1.25ms 1.31ms 736. 222.8KB 6.00 368 3
这适用于 df1
中的重复项。 Rich Scriven 的解决方案更快。在某些极端情况下,基于 merge
的解决方案更可取,因为 Rich Scriven 的解决方案会给出不正确的答案。例如,考虑以下带有整数的示例
df1 <- data.frame(x1 = 11, x2 = 1)
df2 <- data.frame(x1 = 1, x2 = 11)
do.call(paste0, df1) %in% do.call(paste0, df2)
#R> [1] TRUE
rowcheck(df1, df2)
#R> [1] FALSE
row_check_new(df1, df2)
#R> [1] FALSE