微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

如何尽可能高效地比较两个大型数据集的元素?

如何解决如何尽可能高效地比较两个大型数据集的元素?

我是 R 业余爱好者,学习缓慢。我介绍一下情况:

我有两个数据框,其中有几列 (4) 和 +10000 行,如下所示:

df1:                   df2:
Nº x   y   attr        Nº x   y   attr
1  45  34  X           1  34  23  x
1  48  45  XX          4  123 45  x
1  41  23  X           4  99  69  xx
4  23  12  X           4  112 80  xx
4  28  16  X           5  78  80  x
5  78  80  XXX         5  69  74  xx
...

我想比较基于 x,y(坐标)的两个数据框,以删除 df1 中也出现在 df2 中的所有值(两个数据集中包含的所有值/坐标,在 df1 中删除它们)。

所以在我的例子中,df1 的最后一行将被删除,因为相同的坐标在 df2 中。

我正在做的是使用双循环 for(),一个用于一个数据集,另一个用于另一个,将所有可能的值一一比较。 我知道这是非常低效的,而且如果我增加数据量也需要很多时间。

还有什么其他方法可以做到这一点? 可能有一些功能,但我通常不知道如何使用它们,这给我带来了问题。

非常感谢!!

解决方法

不是最优雅的解决方案,但可以完成工作:

df2 = fread('Nº x   y   attr
1  34  23  x
4  123 45  x
4  99  69  xx
4  112 80  xx
5  78  80  x
5  69  74  xx')

df1 = fread('Nº x   y   attr        
1  45  34  X           
1  48  45  XX          
1  41  23  X          
4  23  12  X         
4  28  16  X        
5  78  80  XXX')     
> df1[!stringr::str_c(df1$x,df1$y,sep="_") %in% stringr::str_c(df2$x,df2$y,sep="_"),]
   Nº  x  y attr
1:  1 45 34    X
2:  1 48 45   XX
3:  1 41 23    X
4:  4 23 12    X
5:  4 28 16    X

说明:

最好使用 vectorised 函数而不是循环。 !stringr::str_c(df1$x,sep="_") 将 x 和 y 列连接成一个字符串,然后从 df1 中查找不在 df2 中的元素。这将创建一个由 TRUE FALSE 值组成的逻辑向量,然后我们可以使用它来对 df1 进行子集化。

编辑:

我很好奇我的或@dww 的回答是否更快:

> library(microbenchmark)
> 
> n=100000
> 
> df1 = data.table(x = sample(n),y=sample(n))
> df2 = data.table(x = sample(n),y=sample(n))
> 
> 
> 
> microbenchmark(
... df1[!stringr::str_c(df1$x,],... df1[fsetdiff(df1[,.(x,y)],df2[,y)] ),on=c('x','y')]
... )
Unit: milliseconds
                                                                                              expr
 df1[!stringr::str_c(df1$x,sep = "_") %in% stringr::str_c(df2$x,sep = "_"),]
                                   df1[fsetdiff(df1[,y)]),on = c("x","y")]
       min        lq      mean    median        uq      max neval
 168.40953 199.37183 219.30054 209.61414 222.08134 364.3458   100
  41.07557  42.67679  52.34855  44.34379  59.27378 152.1283   100

似乎 dww 的 data.table 版本快了大约 5 倍。

,

library(data.table) 方法:

df1[fsetdiff(df1[,'y')]
#   Nº  x  y attr
#1:  1 45 34    X
#2:  1 48 45   XX
#3:  1 41 23    X
#4:  4 23 12    X
#5:  4 28 16    X
,

3 行代码

#generate sample data
x1 <- sample(1:50,9001,T)
y1 <- sample(1:50,T)

x2 <- sample(1:50,T)
y2 <- sample(1:50,T)

df1 <- data.frame(id =1:9001,x1,y1,stringsAsFactors = F)
df2 <- data.frame(id =1:9001,x2,y2,stringsAsFactors = F)

#add a match column to each dataframe
df1$match <- paste(df1$x1,df1$y1)
df2$match <- paste(df2$x2,df2$y2)

#overwrite df1 with the date of df1 that does not appear in df2
df1 <- df1[!df1$match %in% df2$match,]

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。