关于r:根据两个相似df之间的对比创建一个新的数据帧

Create a new dataframe according to the contrast between two similar df

本问题已经有最佳答案,请猛点这里访问。

我有一个这样的数据框架:

1
2
3
4
  X Y  Z T
  1 2  4 2
  3 2  1 4
  7 5 NA 3

经过几步(不重要的是哪一步),我得到了这个df:

1
2
3
4
  X Y Z T
  1 2 4 2
  3 2 NA 4
  7 5 NA 3

我想获得一个新的数据帧,该数据帧只由步骤中没有更改的行组成;结果是:

1
2
3
 X  Y  Z  T
 1  2  4  2
 7  5  NA 3

我该怎么办?


您可以使用dplyr的intersect功能:

1
2
3
4
5
library(dplyr)
intersect(d1, d2)
#  X Y  Z T
#1 1 2  4 2
#2 7 5 NA 3

这是一个data.frame等价于base r的intersect函数。

如果您正在使用data.table,该包还提供了这样的功能:

1
2
3
4
5
6
7
library(data.table)
setDT(d1)
setDT(d2)
fintersect(d1, d2)
#   X Y  Z T
#1: 1 2  4 2
#2: 7 5 NA 3

使用base R的一个选项是使用paste将每个数据集的行放在一起进行比较(==以创建一个逻辑向量,用于对新数据集进行子集设置。

1
2
3
4
dfO[do.call(paste, dfO) == do.call(paste, df),]
#   X Y  Z T
#1 1 2  4 2
#3 7 5 NA 3

其中"dfo"是旧数据集,"df"是新数据集


恐怕江户一八、江户一三、江户一十都不是正确答案。mergeintersect无法正确处理重复行。半联接将更改行的顺序。

从这个角度来看,我认为目前唯一正确的是Akrun的。

你也可以做如下的事情:

1
df1[rowSums(((df1 == df2) | (is.na(df1) & is.na(df2))), na.rm = T) == ncol(df1),]

但我认为Akrun的方式更优雅,在速度方面可能表现更好。


另一个dplyr解决方案:semi_join

1
2
3
4
dt1 %>% semi_join(dt2, by = colnames(.))
  X Y  Z T
1 1 2  4 2
2 7 5 NA 3

数据

1
2
3
4
5
6
7
8
9
10
11
dt1 <- read.table(text ="X Y  Z T
  1 2  4 2
  3 2  1 4
  7 5 NA 3",
                  header = TRUE, stringsAsFactors = FALSE)

dt2 <- read.table(text ="  X Y Z T
  1 2 4 2
                  3 2 NA 4
                  7 5 NA 3",
                  header = TRUE, stringsAsFactors = FALSE)