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

これら 2 つのデータ フレームのセット操作を実行する必要があります。merge(df1,df2,all=TRUE)andメソッドを使用しmerge(df1,df2,all=FALSE)て、これらのデータ フレームの結合と交差を取得し、必要な出力を得ました。これらのデータ フレームのマイナスを取得する関数は何ですか。つまり、1 つのデータ フレームに存在するが他のデータ フレームには存在しないすべての位置です。次の出力が必要です。

 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 に答える
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 に答える
2

https://stackoverflow.com/a/16144262/2055486の 1 つの問題は、どちらのデータ フレームにも重複した行がないことを前提としていることです。次の関数はその制限を取り除き、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 に答える