2

我有两个巨大的数据框,其中一张表包含较少的观察结果。dplyr 的反连接工作完美且快速,但如果可能,我会保留原始行名。任何功能/包都允许以 anti_join 的速度进行此操作?我目前的解决方案

library(magrittr)
library(dplyr)

iris
iris2 <- iris[-c(3, 9, 30, 40), ]

iris <- iris %>% mutate(rown = 1:n())

anti_join(iris, iris2) %>% set_rownames(.$rown) %>% select(-rown)

编辑:寻找我不需要添加行号的解决方案。

4

2 回答 2

1

dplyr的 setdiff

setdiff(iris, iris2)

它比 anti_join 有点麻烦,因为它属于传统的集合操作之流并且需要匹配列,但这是一个很好的用例。

完整的例子:

iris <- 
    iris %>% 
    mutate(rown = 1:n())

iris2 <-
    iris[-c(3, 9, 30, 40), ] 

setdiff(iris, iris2)
> setdiff(iris, iris2)
  Sepal.Length Sepal.Width Petal.Length Petal.Width Species rown
1          4.7         3.2          1.3         0.2  setosa    3
2          4.4         2.9          1.4         0.2  setosa    9
3          4.7         3.2          1.6         0.2  setosa   30
4          5.1         3.4          1.5         0.2  setosa   40

但是,我也重新运行了 Federico 的基本 R 解决方案,结果证明这which并不是显着缩短时间的唯一因素。使用基本 R 方法生成 rownumbers 列而不是 mutate 可以大大减少处理时间。

在任何情况下,如果您只是将 aniris$rown<-seq(1,dim(iris)[1],1)放入原始代码中,并且不费心重新编号您的行,您会看到处理时间的健康下降。which仍然勉强获胜,尽管我个人发现这里牺牲的微秒非常值得setdiff(bigTbl, smallTbl).

完整的分析集是这样的:

antjn_set_rwnms=function(){
    iris  <- iris  %>% mutate(rown = 1:n())
    iris2 <- iris [-c(3, 9, 30, 40), ]
    anti_join(iris , iris2) %>% set_rownames(.$rown) %>% select(-rown)
}
antjn_rwnum=function(){
    iris <- iris %>% mutate(rown = row_number())
    iris2 <- iris[-c(3, 9, 30, 40), ]
    anti_join(iris, iris2)
}
antjn_1n=function(){
    iris <- iris %>% mutate(rown = 1:n())
    iris2 <- iris[-c(3, 9, 30, 40), ]
    anti_join(iris, iris2)
}
stdff_seq=function(){
    iris$rown<-seq(1,dim(iris)[1],1)
    iris2 <- iris[-c(3, 9, 30, 40), ]
    setdiff(iris, iris2)
}
stdff_rwnum=function(){
    iris <- iris %>% mutate(rown = row_number())
    iris2 <- iris[-c(3, 9, 30, 40), ]
    setdiff(iris, iris2)
}
stdff_1n=function(){
    iris <- iris %>% mutate(rown = 1:n())
    iris2 <- iris[-c(3, 9, 30, 40), ]
    setdiff(iris, iris2)
}
whch_1n=function(){
    iris <- iris %>% mutate(rown = 1:n())
    iris2 <- iris[-c(3, 9, 30, 40), ]
    iris[which(!(iris$rown %in% iris2$rown)),]
}
whch_seq=function(){
    iris$rown<-seq(1,dim(iris)[1],1)
    iris2 <- iris[-c(3, 9, 30, 40), ]
    iris[which(!(iris$rown %in% iris2$rown)),]
}
antjn_seq=function(){
    iris$rown<-seq(1,dim(iris)[1],1)
    iris2 <- iris[-c(3, 9, 30, 40), ]
    anti_join(iris, iris2)
}


microbenchmark(
               antjn_set_rwnms(),
               antjn_rwnum(),
               antjn_1n(),
               stdff_1n(),
               stdff_rwnum(),
               whch_1n(),
               antjn_seq(),
               stdff_seq(),
               whch_seq(),
               times = 10000L)

产生以下结果:

Unit: microseconds
              expr      min       lq      mean   median        uq      max neval
 antjn_set_rwnms() 2858.014 3343.828 4268.2085 3891.226 4890.2260 97763.88 10000
     antjn_rwnum() 2273.410 2612.540 3401.6724 3043.615 3897.2130 89484.50 10000
        antjn_1n() 2278.114 2617.886 3371.6463 3048.748 3899.7790 75887.23 10000
        stdff_1n() 1390.305 1591.302 2117.1687 1852.385 2465.6405 88135.68 10000
     stdff_rwnum() 1383.034 1581.466 2073.9099 1811.329 2421.8065 59467.88 10000
         whch_1n() 1347.539 1550.247 2083.1022 1810.261 2405.1275 76800.70 10000
       antjn_seq() 1168.779 1406.555 1847.2465 1621.024 2112.1845 87611.37 10000
       stdff_seq()  336.564  421.668  567.4554  480.684  660.2985 64252.05 10000
        whch_seq()  285.246  382.323  514.1107  437.063  595.7225 16619.50 10000
于 2017-05-08T08:38:45.820 回答
1

普通的 R 呢?

iris$rows<-seq(1,dim(iris)[1],1)
iris2 <- iris[-c(3, 9, 30, 40), ]
iris[which(!(iris$rows %in% iris2$rows)),]

时间比较

iris <- iris %>% mutate(rown = 1:n())
iris$rows<-seq(1,dim(iris)[1],1)
 iris2 <- iris[-c(3, 9, 30, 40), ]


    f=function(){
      anti_join(iris, iris2) %>% set_rownames(.$rown) %>% select(-rown)
    }


f2=function(){
  iris[which(!(iris$rows %in% iris2$rows)),]   
}

    microbenchmark(f(),f2())

 expr      min        lq      mean   median       uq      max neval
  f() 1531.523 1832.0710 2384.1375 2407.061 2828.096 4084.061   100
 f2()  104.869  168.0125  238.7027  235.396  290.284  513.185   100

不使用任何行号

mtcars 
mtcars2<-mtcars[-c(3,9,40),]
mtcars[which(!row.names(mtcars) %in% row.names(mtcars2)),]

希望能帮助到你

于 2017-05-08T07:54:29.383 回答