23

我有 2 个数据框 df1df2.

df1 <- data.frame(c1=c("a","b","c","d"),c2=c(1,2,3,4) )
df2 <- data.frame(c1=c("c","d","e","f"),c2=c(3,4,5,6) )

> df1
  c1 c2
1  a  1
2  b  2
3  c  3
4  d  4

> df2
  c1 c2
1  c  3
2  d  4
3  e  5
4  f  6

我需要对这两个数据帧进行设置操作。我使用merge(df1,df2,all=TRUE)andmerge(df1,df2,all=FALSE)方法来获取这些数据帧的并集和交集,并得到所需的输出。获得这些数据帧的负数的功能是什么,即一个数据帧上存在的所有位置,但另一个数据帧上不存在?我需要以下输出。

 c1 c2
1  a  1
2  b  2
4

9 回答 9

32

我记得几个月前遇到过这个确切的问题。设法筛选了我的 Evernote 单行字。

注意:这不是我的解决方案。归功于写它的人(我目前似乎找不到)。

如果您不担心,rownames那么您可以这样做:

df1[!duplicated(rbind(df2, df1))[-seq_len(nrow(df2))], ]
#   c1 c2
# 1  a  1
# 2  b  2

编辑:一个data.table解决方案:

dt1 <- data.table(df1, key="c1")
dt2 <- data.table(df2)
dt1[!dt2]

或更好的单线(来自 v1.9.6+):

setDT(df1)[!df2, on="c1"]

df1这将返回wheredf2$c1与 不匹配的所有行df1$c1

于 2013-04-22T09:58:45.997 回答
10

我更喜欢sqldf包:

require(sqldf)
sqldf("select * from df1 except select * from df2")

##   c1 c2
## 1  a  1
## 2  b  2
于 2013-04-22T09:39:59.213 回答
4

您可以创建标识符列作为子集:

例如

df1 <- data.frame(c1=c("a","b","c","d"),c2=c(1,2,3,4), indf1 = rep("Y",4) )
df2 <- data.frame(c1=c("c","d","e","f"),c2=c(3,4,5,6),indf2 = rep("Y",4) )
merge(df1,df2)
#  c1 c2 indf1 indf2
#1  c  3     Y     Y
#2  d  4     Y     Y

bigdf <- merge(df1,df2,all=TRUE)
#  c1 c2 indf1 indf2
#1  a  1     Y  <NA>
#2  b  2     Y  <NA>
#3  c  3     Y     Y
#4  d  4     Y     Y
#5  e  5  <NA>     Y
#6  f  6  <NA>     Y

然后按照您的意愿进行子集化:

 bigdf[is.na(bigdf$indf1) ,]
#  c1 c2 indf1 indf2
#5  e  5  <NA>     Y
#6  f  6  <NA>     Y

 bigdf[is.na(bigdf$indf2) ,]  #<- output you requested those not in df2
#  c1 c2 indf1 indf2
#1  a  1     Y  <NA>
#2  b  2     Y  <NA>
于 2013-04-22T09:31:09.120 回答
4

我认为最简单的解决方案是使用 dplyr (tidyverse)。

require(tidyverse)
anti_join(df1, df2)
于 2018-08-06T09:00:49.190 回答
2

https://stackoverflow.com/a/16144262/2055486的一个问题是它假设两个数据框都没有重复的行。以下函数消除了该限制,也适用于 x 或 y 中的任意用户定义列。

duplicated.data.frame该实现使用与使用分隔符将列连接在一起的实现类似的想法。duplicated.data.frame使用"\r",如果条目具有嵌入的"\r"字符,这可能会导致冲突。这使用了ASCII 记录分隔符 "\30",它出现在输入数据中的机会要低得多。

setdiff.data.frame <- function(x, y,
    by = intersect(names(x), names(y)),
    by.x = by, by.y = by) {
  stopifnot(
    is.data.frame(x),
    is.data.frame(y),
    length(by.x) == length(by.y))

  !do.call(paste, c(x[by.x], sep = "\30")) %in% do.call(paste, c(y[by.y], sep = "\30"))
}

# Example usage
# remove all 4 or 6 cylinder 4 gear cars or 8 cylinder 3 gear rows
to_remove <- data.frame(cyl = c(4, 6, 8), gear = c(4, 4, 3))
mtcars[setdiff.data.frame(mtcars, to_remove), ]
#>                 mpg cyl  disp  hp drat    wt  qsec vs am gear carb
#> Hornet 4 Drive 21.4   6 258.0 110 3.08 3.215 19.44  1  0    3    1
#> Valiant        18.1   6 225.0 105 2.76 3.460 20.22  1  0    3    1
#> Toyota Corona  21.5   4 120.1  97 3.70 2.465 20.01  1  0    3    1
#> Porsche 914-2  26.0   4 120.3  91 4.43 2.140 16.70  0  1    5    2
#> Lotus Europa   30.4   4  95.1 113 3.77 1.513 16.90  1  1    5    2
#> Ford Pantera L 15.8   8 351.0 264 4.22 3.170 14.50  0  1    5    4
#> Ferrari Dino   19.7   6 145.0 175 3.62 2.770 15.50  0  1    5    6
#> Maserati Bora  15.0   8 301.0 335 3.54 3.570 14.60  0  1    5    8

# with differing column names
to_remove2 <- data.frame(a = c(4, 6, 8), b = c(4, 4, 3))
mtcars[setdiff.data.frame(mtcars, to_remove2, by.x = c("cyl", "gear"), by.y = c("a", "b")), ]
#>                 mpg cyl  disp  hp drat    wt  qsec vs am gear carb
#> Hornet 4 Drive 21.4   6 258.0 110 3.08 3.215 19.44  1  0    3    1
#> Valiant        18.1   6 225.0 105 2.76 3.460 20.22  1  0    3    1
#> Toyota Corona  21.5   4 120.1  97 3.70 2.465 20.01  1  0    3    1
#> Porsche 914-2  26.0   4 120.3  91 4.43 2.140 16.70  0  1    5    2
#> Lotus Europa   30.4   4  95.1 113 3.77 1.513 16.90  1  1    5    2
#> Ford Pantera L 15.8   8 351.0 264 4.22 3.170 14.50  0  1    5    4
#> Ferrari Dino   19.7   6 145.0 175 3.62 2.770 15.50  0  1    5    6
#> Maserati Bora  15.0   8 301.0 335 3.54 3.570 14.60  0  1    5    8
于 2016-01-06T17:36:31.900 回答
1

您可以像这样检查列和子集中的值(只需添加另一个解决方案):

na.omit( df1[ sapply( 1:ncol(df1) , function(x) ! df1[,x] %in% df2[,x] ) , ] )
#  c1 c2
#1  a  1
#2  b  2
于 2013-04-22T10:55:25.743 回答
1

如果您不打算使用 中的任何实际数据d2,那么您根本不需要merge

df1[!(df1$c1 %in% df2$c1), ]
于 2013-04-22T09:34:40.460 回答
0

您可以dplyr::setdiff轻松使用

dplyr::setdiff(iris, iris[iris$Sepal.Length >6,])

   Sepal.Length Sepal.Width Petal.Length Petal.Width    Species
1           5.1         3.5          1.4         0.2     setosa
2           4.9         3.0          1.4         0.2     setosa
3           4.7         3.2          1.3         0.2     setosa
4           4.6         3.1          1.5         0.2     setosa
5           5.0         3.6          1.4         0.2     setosa
6           5.4         3.9          1.7         0.4     setosa
7           4.6         3.4          1.4         0.3     setosa
8           5.0         3.4          1.5         0.2     setosa
9           4.4         2.9          1.4         0.2     setosa
10          4.9         3.1          1.5         0.1     setosa
11          5.4         3.7          1.5         0.2     setosa
12          4.8         3.4          1.6         0.2     setosa
13          4.8         3.0          1.4         0.1     setosa
14          4.3         3.0          1.1         0.1     setosa
15          5.8         4.0          1.2         0.2     setosa
16          5.7         4.4          1.5         0.4     setosa
17          5.4         3.9          1.3         0.4     setosa
18          5.1         3.5          1.4         0.3     setosa
19          5.7         3.8          1.7         0.3     setosa
20          5.1         3.8          1.5         0.3     setosa
21          5.4         3.4          1.7         0.2     setosa
22          5.1         3.7          1.5         0.4     setosa
23          4.6         3.6          1.0         0.2     setosa
24          5.1         3.3          1.7         0.5     setosa
25          4.8         3.4          1.9         0.2     setosa
26          5.0         3.0          1.6         0.2     setosa
27          5.0         3.4          1.6         0.4     setosa
28          5.2         3.5          1.5         0.2     setosa
29          5.2         3.4          1.4         0.2     setosa
30          4.7         3.2          1.6         0.2     setosa
31          4.8         3.1          1.6         0.2     setosa
32          5.4         3.4          1.5         0.4     setosa
33          5.2         4.1          1.5         0.1     setosa
34          5.5         4.2          1.4         0.2     setosa
35          4.9         3.1          1.5         0.2     setosa
36          5.0         3.2          1.2         0.2     setosa
37          5.5         3.5          1.3         0.2     setosa
38          4.9         3.6          1.4         0.1     setosa
39          4.4         3.0          1.3         0.2     setosa
40          5.1         3.4          1.5         0.2     setosa
41          5.0         3.5          1.3         0.3     setosa
42          4.5         2.3          1.3         0.3     setosa
43          4.4         3.2          1.3         0.2     setosa
44          5.0         3.5          1.6         0.6     setosa
45          5.1         3.8          1.9         0.4     setosa
46          4.8         3.0          1.4         0.3     setosa
47          5.1         3.8          1.6         0.2     setosa
48          4.6         3.2          1.4         0.2     setosa
49          5.3         3.7          1.5         0.2     setosa
50          5.0         3.3          1.4         0.2     setosa
51          5.5         2.3          4.0         1.3 versicolor
52          5.7         2.8          4.5         1.3 versicolor
53          4.9         2.4          3.3         1.0 versicolor
54          5.2         2.7          3.9         1.4 versicolor
55          5.0         2.0          3.5         1.0 versicolor
56          5.9         3.0          4.2         1.5 versicolor
57          6.0         2.2          4.0         1.0 versicolor
58          5.6         2.9          3.6         1.3 versicolor
59          5.6         3.0          4.5         1.5 versicolor
60          5.8         2.7          4.1         1.0 versicolor
61          5.6         2.5          3.9         1.1 versicolor
62          5.9         3.2          4.8         1.8 versicolor
63          6.0         2.9          4.5         1.5 versicolor
64          5.7         2.6          3.5         1.0 versicolor
65          5.5         2.4          3.8         1.1 versicolor
66          5.5         2.4          3.7         1.0 versicolor
67          5.8         2.7          3.9         1.2 versicolor
68          6.0         2.7          5.1         1.6 versicolor
69          5.4         3.0          4.5         1.5 versicolor
70          6.0         3.4          4.5         1.6 versicolor
71          5.6         3.0          4.1         1.3 versicolor
72          5.5         2.5          4.0         1.3 versicolor
73          5.5         2.6          4.4         1.2 versicolor
74          5.8         2.6          4.0         1.2 versicolor
75          5.0         2.3          3.3         1.0 versicolor
76          5.6         2.7          4.2         1.3 versicolor
77          5.7         3.0          4.2         1.2 versicolor
78          5.7         2.9          4.2         1.3 versicolor
79          5.1         2.5          3.0         1.1 versicolor
80          5.7         2.8          4.1         1.3 versicolor
81          5.8         2.7          5.1         1.9  virginica
82          4.9         2.5          4.5         1.7  virginica
83          5.7         2.5          5.0         2.0  virginica
84          5.8         2.8          5.1         2.4  virginica
85          6.0         2.2          5.0         1.5  virginica
86          5.6         2.8          4.9         2.0  virginica
87          6.0         3.0          4.8         1.8  virginica
88          5.9         3.0          5.1         1.8  virginica
于 2021-02-06T02:39:25.213 回答
0

使用基本 R 的另一种方法(包括保留行名并检查所有行)是双重使用duplicated()

df1 <- data.frame(c1=c("a","b","c","d"),c2=c(1,2,3,4) )
df2 <- data.frame(c1=c("c","d","e","f"),c2=c(3,4,5,6) )

all <- rbind(df1, df2)
all[!duplicated(all) & !duplicated(all, fromLast = TRUE), ]
  
于 2021-01-31T18:19:16.840 回答