dplyrを使用して重複行を削除する


128

私はこのようなdata.frameを持っています-

set.seed(123)
df = data.frame(x=sample(0:1,10,replace=T),y=sample(0:1,10,replace=T),z=1:10)
> df
   x y  z
1  0 1  1
2  1 0  2
3  0 1  3
4  1 1  4
5  1 0  5
6  0 1  6
7  1 0  7
8  1 0  8
9  1 0  9
10 0 1 10

最初の2つの列に基づいて重複行を削除したいと思います。期待される出力-

df[!duplicated(df[,1:2]),]
  x y z
1 0 1 1
2 1 0 2
4 1 1 4

dplyrパッケージを使用したソリューションを具体的に探しています。

回答:


137

dplyr現在distinct、この目的のための関数が含まれています。

以下の元の答え:


library(dplyr)
set.seed(123)
df <- data.frame(
  x = sample(0:1, 10, replace = T),
  y = sample(0:1, 10, replace = T),
  z = 1:10
)

1つのアプローチは、グループ化し、最初の行のみを保持することです。

df %>% group_by(x, y) %>% filter(row_number(z) == 1)

## Source: local data frame [3 x 3]
## Groups: x, y
## 
##   x y z
## 1 0 1 1
## 2 1 0 2
## 3 1 1 4

(dplyr 0.2では、ダミーz変数は必要なく、単に書き込むことができますrow_number() == 1

次のslice()ように機能する関数を追加することも考えています。

df %>% group_by(x, y) %>% slice(from = 1, to = 1)

または、そのバリエーションunique()を使用して、使用する変数を選択できます。

df %>% unique(x, y)

4
@dotcomkenそれまではそのまま使用することもできますdf %>% group_by(x, y) %>% do(head(.,1))
Holger Brandl

16
@MahbubulMajumderは動作しますが、かなり遅いです。dplyr 0.3にはdistinct()
ハドリー2014

3
@hadley私はunique()とdistinct()関数が好きですが、それらはすべてデータフレームから2番目の重複を削除します。重複する値の最初の遭遇をすべて削除したい場合はどうなりますか?これはどのように行うことができますか?助けてくれてありがとう!
FlyingDutch

2
@MvZB-単に(desc())を配置してから、distinctを使用しませんか?
ウッドストック

簡単な解決策があると確信していますが、重複する両方の行を削除するにはどうすればよいですか?私は生物学的サンプルに関連付けられたメタデータを使用することが多く、サンプルIDが重複している場合、どの行に正しいデータがあるのか​​確信が持てません。最も安全な方法は、誤ったメタデータの関連付けを回避するために両方をダンプすることです。重複するサンプルIDのリストを作成し、それらのIDで行を除外する以外に簡単な解決策はありますか?
glongo_fishes

191

これはを使用したソリューションdplyr >= 0.5です。

library(dplyr)
set.seed(123)
df <- data.frame(
  x = sample(0:1, 10, replace = T),
  y = sample(0:1, 10, replace = T),
  z = 1:10
)

> df %>% distinct(x, y, .keep_all = TRUE)
    x y z
  1 0 1 1
  2 1 0 2
  3 1 1 4

3
このソリューションは、Hadleyが提供するソリューションよりもはるかに高速です(私の場合は10倍)。
Calimo 2014年

101
技術的には、これもHadleyが提供するソリューションです:-)
Tyler Rinker

27

完全を期すために、以下も機能します。

df %>% group_by(x) %>% filter (! duplicated(y))

ただし、私はを使用したソリューションを好み、distinctそれもより高速であると思います。


7

ほとんどの場合、distinct()すでに提案されているように、最良のソリューションはdplyrから使用することです。

ただし、slice()dplyr の関数を使用する別のアプローチを次に示します。

# Generate fake data for the example
  library(dplyr)
  set.seed(123)
  df <- data.frame(
    x = sample(0:1, 10, replace = T),
    y = sample(0:1, 10, replace = T),
    z = 1:10
  )

# In each group of rows formed by combinations of x and y
# retain only the first row

    df %>%
      group_by(x, y) %>%
      slice(1)

distinct()関数との違い

このソリューションの利点は、元のデータフレームからどの行が保持されるかを明確にし、arrange()関数と適切に組み合わせることができることです。

顧客の販売データがあり、顧客ごとに1つのレコードを保持し、そのレコードを最新の購入からのレコードにしたいとします。それからあなたは書くことができます:

customer_purchase_data %>%
   arrange(desc(Purchase_Date)) %>%
   group_by(Customer_ID) %>%
   slice(1)

3

データセットを削減するためにRで列を選択すると、多くの場合、重複が発生する可能性があります。

これらの2行は同じ結果になります。それぞれ、2つの列のみが選択された一意のデータセットを出力します。

distinct(mtcars, cyl, hp);

summarise(group_by(mtcars, cyl, hp));

1

重複している行を検索する場合は、find_duplicatesfrom を使用できますhablar

library(dplyr)
library(hablar)

df <- tibble(a = c(1, 2, 2, 4),
             b = c(5, 2, 2, 8))

df %>% find_duplicates()
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.