製造系SEのメモ

普段気になった内容をメモしていきます

Rのdplyrを用いて重複している行のみを抽出

f:id:asakat:20190130204302j:plain

Rのパッケージ「dplyr」の初心者で、重複している行のみの抽出方法をよく忘れるのでメモします。

※dplyrを使う際には以下のページを参考にしています。
qiita.com
qiita.com
qiita.com

テストデータ

10行×3列のデータを適当に作りました。

> testdata
   gender bloodtype age
1    male         B  26
2  female         A  43
3    male         B  33
4  female         A  48
5    male        AB  27
6    male         A  39
7    male         O  38
8    male         B  33
9  female         A  43
10   male        AB  33

2行目と9行目、3行目と8行目が重複しています。

これにdplyrのdistinct()を使うと…

> distinct(testdata)
  gender bloodtype age
1   male          B  26
2 female          A  43
3   male          B  33
4 female          A  48
5   male         AB  27
6   male          A  39
7   male          O  38
8   male         AB  33

重複行削除はしてくれますが、どの行が重複していたのかが分かりません。

重複している行のみの抽出

テストデータの場合、これでできました。

group_by(gender, bloodtype, age) %>%  filter(n() > 1)

gender、bloodtype、ageが同じものをグループ化して、1つのグループ内に2行以上存在するグループ(重複している行)を抽出します。

実際に実行すると以下の通りです。

> testdata %>% group_by(gender, bloodtype, age) %>%
+   filter(n() > 1)
# A tibble: 4 x 3
# Groups:   gender, bloodtype, age [2]
  gender bloodtype   age
  <fct>  <fct>     <int>
1 female A            43
2 male   B            33
3 male   B            33
4 female A            43

この中での重複を削除したい場合は

group_by(gender, bloodtype, age) %>%  filter(n() > 1) %>% distinct()

というようにdistinct()を追記します。

重複していない行のみの抽出

逆に重複していない行のみを抽出したい場合は、filter(n() == 1)にすれば良いですね。

> testdata %>% group_by(gender, bloodtype, age) %>%
+   filter(n() == 1)
# A tibble: 6 x 3
# Groups:   gender, bloodtype, age [6]
  gender bloodtype   age
  <fct>  <fct>     <int>
1 male   B            26
2 female A            48
3 male   AB           27
4 male   A            39
5 male   O            38
6 male   AB           33

distinct()は重複行を削除(重複を無くす)する関数であり、重複していない行のみを抽出する関数ではないことを忘れがちなので気をつけます(自分が)。

(おまけ)重複行を特定しやすくする

テストデータには行番号を振っていないので行数が増えると重複行の特定が難しいですが、dplyrのrow_number()関数を使うことで特定しやすくなります。

> testdata %>% mutate(No = row_number()) %>%
+   group_by(gender, bloodtype, age) %>%
+   filter(n() > 1)
# A tibble: 4 x 4
# Groups:   gender, bloodtype, age [2]
  gender bloodtype   age    No
  <fct>  <fct>     <int> <int>
1 female A            43     2
2 male   B            33     3
3 male   B            33     8
4 female A            43     9

以上です。