web-dev-qa-db-ja.com

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

私はこのような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パッケージを使用したソリューションを具体的に探しています。

105
Nishanth

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)
115
hadley

dplyr 0.3を使用したソリューションを次に示します。

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)
    x y z
  1 0 1 1
  2 1 0 2
  3 1 1 4

dplyr 0.5用に更新

distinct()のdplyrバージョン0.5のデフォルトの動作は、...引数で指定された列のみを返します。

元の結果を得るには、次を使用する必要があります。

df %>% distinct(x, y, .keep_all = TRUE)
174
davechilders

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

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

ただし、distinctを使用したソリューションの方が好みです。これも高速だと思います。

24
Konrad Rudolph

縮小されたデータセットのRの列を選択する場合、多くの場合、重複することになります。

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

distinct(mtcars, cyl, hp);

summarise(group_by(mtcars, cyl, hp));
2
Anton Andreev

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

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

# 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)
1
bschneidr

重複する行を検索する場合は、hablarからfind_duplicatesを使用できます。

library(dplyr)
library(hablar)

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

df %>% find_duplicates()
0
davsjob