Rのduplicated関数を使ってデータフレームの重複チェック(改)
duplicated関数の引数にデータフレームを指定すると、すべての項目(列)を組み合わせた上での重複チェックができますよ、という話を以前書きました↓
Rのデータフレームで複数項目を組み合わせた重複のチェック - Rプログラミングの小ネタ
また、上記の記事では、すべてではなく一部の項目のみを組み合わせ対象にしたい場合は、interaction関数を使って新たにチェック用の列を作ってはどう?、というやり方も紹介しました。
が、duplicated関数がすべての列を対象にする動きなら、対象にしたい列だけで構成された新たなデータフレームを生成して、duplicated関数に渡した方がシンプルではないか、ということに気づきました。
例えば↓こんなデータがあって、
> d
名字 名前 年齢
1 伊東 二郎 52
2 佐藤 五郎 52
3 遠藤 太郎 53
4 後藤 太郎 53
5 近藤 五郎 28
6 遠藤 二郎 33
7 後藤 四郎 52
8 須藤 次郎 28
9 伊東 二郎 35
10 遠藤 太郎 23
11 遠藤 史郎 38
12 工藤 吾郎 53
13 須藤 太郎 22
14 武藤 二郎 28
15 工藤 吾郎 53
16 伊東 二郎 22
17 遠藤 四郎 33
18 後藤 史郎 38
19 加藤 一郎 28
20 加藤 二郎 22
名字と名前だけを対象として重複チェックをしたい場合は、
> sum(duplicated( data.frame(d$名字, d$名前) ))
[1] 4
とか、
> d[duplicated( data.frame(d$名字, d$名前) ), ]
名字 名前 年齢
9 伊東 二郎 35
10 遠藤 太郎 23
15 工藤 吾郎 53
16 伊東 二郎 22
という感じですね。interaction関数を使うよりも、シンプルだと思います。
が、duplicated関数の仕様って、2つ目以降が現れたときにTRUEとなる、というものなんですよね。つまり、伊東二郎さんが3回現れる場合、1つ目はFALSE、2つ目はTRUE、3つ目はTRUEという結果になります。なので、sum関数で数えた場合の結果は「2」となるし。TRUEのものを表示させようとすると上記の例のように、1つ目の伊東二郎さんは表示されないことになってしまいます。
重複の有無だけを確認したい場合は上記でもよさそうですが、重複したものをすべて確認したいという場合は、interaction関数を使ってチェック用の列を作った方がいいかもしれません。↓こんな感じ。(分かりやすいように、いちいち表示させてます)
> # チェック用の「氏名」列を作る
> d$氏名 <- interaction(d$名字, d$名前, drop=T)
> d
名字 名前 年齢 氏名
1 伊東 二郎 52 伊東.二郎
2 佐藤 五郎 52 佐藤.五郎
3 遠藤 太郎 53 遠藤.太郎
4 後藤 太郎 53 後藤.太郎
5 近藤 五郎 28 近藤.五郎
6 遠藤 二郎 33 遠藤.二郎
7 後藤 四郎 52 後藤.四郎
8 須藤 次郎 28 須藤.次郎
9 伊東 二郎 35 伊東.二郎
10 遠藤 太郎 23 遠藤.太郎
11 遠藤 史郎 38 遠藤.史郎
12 工藤 吾郎 53 工藤.吾郎
13 須藤 太郎 22 須藤.太郎
14 武藤 二郎 28 武藤.二郎
15 工藤 吾郎 53 工藤.吾郎
16 伊東 二郎 22 伊東.二郎
17 遠藤 四郎 33 遠藤.四郎
18 後藤 史郎 38 後藤.史郎
19 加藤 一郎 28 加藤.一郎
20 加藤 二郎 22 加藤.二郎
> # 重複している行を抽出
> dup <- d[duplicated(d$氏名), ]
> dup
名字 名前 年齢 氏名
9 伊東 二郎 35 伊東.二郎
10 遠藤 太郎 23 遠藤.太郎
15 工藤 吾郎 53 工藤.吾郎
16 伊東 二郎 22 伊東.二郎
> # 2回以上登場(=元のデータに3回以上登場)への対策
> dup_u <- unique(dup$氏名)
> dup_u
[1] 伊東.二郎 遠藤.太郎 工藤.吾郎
16 Levels: 加藤.一郎 近藤.五郎 佐藤.五郎 工藤.吾郎 遠藤.史郎 後藤.史郎 ... 武藤.二郎
> # ダブりのあったものを一覧として表示
> for(i in 1:length(dup_u)){
+ print( d[which(d$氏名 == dup_u[i]), ] )
+ cat("---------------------------\n")
+ }
名字 名前 年齢 氏名
1 伊東 二郎 52 伊東.二郎
9 伊東 二郎 35 伊東.二郎
16 伊東 二郎 22 伊東.二郎
---------------------------
名字 名前 年齢 氏名
3 遠藤 太郎 53 遠藤.太郎
10 遠藤 太郎 23 遠藤.太郎
---------------------------
名字 名前 年齢 氏名
12 工藤 吾郎 53 工藤.吾郎
15 工藤 吾郎 53 工藤.吾郎
---------------------------
これで、重複のあった対象の1つ目のものも確認できるようになりました。
Rのデータフレームで複数項目を組み合わせた重複のチェック - Rプログラミングの小ネタ
また、上記の記事では、すべてではなく一部の項目のみを組み合わせ対象にしたい場合は、interaction関数を使って新たにチェック用の列を作ってはどう?、というやり方も紹介しました。
が、duplicated関数がすべての列を対象にする動きなら、対象にしたい列だけで構成された新たなデータフレームを生成して、duplicated関数に渡した方がシンプルではないか、ということに気づきました。
例えば↓こんなデータがあって、
> d
名字 名前 年齢
1 伊東 二郎 52
2 佐藤 五郎 52
3 遠藤 太郎 53
4 後藤 太郎 53
5 近藤 五郎 28
6 遠藤 二郎 33
7 後藤 四郎 52
8 須藤 次郎 28
9 伊東 二郎 35
10 遠藤 太郎 23
11 遠藤 史郎 38
12 工藤 吾郎 53
13 須藤 太郎 22
14 武藤 二郎 28
15 工藤 吾郎 53
16 伊東 二郎 22
17 遠藤 四郎 33
18 後藤 史郎 38
19 加藤 一郎 28
20 加藤 二郎 22
名字と名前だけを対象として重複チェックをしたい場合は、
> sum(duplicated( data.frame(d$名字, d$名前) ))
[1] 4
とか、
> d[duplicated( data.frame(d$名字, d$名前) ), ]
名字 名前 年齢
9 伊東 二郎 35
10 遠藤 太郎 23
15 工藤 吾郎 53
16 伊東 二郎 22
という感じですね。interaction関数を使うよりも、シンプルだと思います。
が、duplicated関数の仕様って、2つ目以降が現れたときにTRUEとなる、というものなんですよね。つまり、伊東二郎さんが3回現れる場合、1つ目はFALSE、2つ目はTRUE、3つ目はTRUEという結果になります。なので、sum関数で数えた場合の結果は「2」となるし。TRUEのものを表示させようとすると上記の例のように、1つ目の伊東二郎さんは表示されないことになってしまいます。
重複の有無だけを確認したい場合は上記でもよさそうですが、重複したものをすべて確認したいという場合は、interaction関数を使ってチェック用の列を作った方がいいかもしれません。↓こんな感じ。(分かりやすいように、いちいち表示させてます)
> # チェック用の「氏名」列を作る
> d$氏名 <- interaction(d$名字, d$名前, drop=T)
> d
名字 名前 年齢 氏名
1 伊東 二郎 52 伊東.二郎
2 佐藤 五郎 52 佐藤.五郎
3 遠藤 太郎 53 遠藤.太郎
4 後藤 太郎 53 後藤.太郎
5 近藤 五郎 28 近藤.五郎
6 遠藤 二郎 33 遠藤.二郎
7 後藤 四郎 52 後藤.四郎
8 須藤 次郎 28 須藤.次郎
9 伊東 二郎 35 伊東.二郎
10 遠藤 太郎 23 遠藤.太郎
11 遠藤 史郎 38 遠藤.史郎
12 工藤 吾郎 53 工藤.吾郎
13 須藤 太郎 22 須藤.太郎
14 武藤 二郎 28 武藤.二郎
15 工藤 吾郎 53 工藤.吾郎
16 伊東 二郎 22 伊東.二郎
17 遠藤 四郎 33 遠藤.四郎
18 後藤 史郎 38 後藤.史郎
19 加藤 一郎 28 加藤.一郎
20 加藤 二郎 22 加藤.二郎
> # 重複している行を抽出
> dup <- d[duplicated(d$氏名), ]
> dup
名字 名前 年齢 氏名
9 伊東 二郎 35 伊東.二郎
10 遠藤 太郎 23 遠藤.太郎
15 工藤 吾郎 53 工藤.吾郎
16 伊東 二郎 22 伊東.二郎
> # 2回以上登場(=元のデータに3回以上登場)への対策
> dup_u <- unique(dup$氏名)
> dup_u
[1] 伊東.二郎 遠藤.太郎 工藤.吾郎
16 Levels: 加藤.一郎 近藤.五郎 佐藤.五郎 工藤.吾郎 遠藤.史郎 後藤.史郎 ... 武藤.二郎
> # ダブりのあったものを一覧として表示
> for(i in 1:length(dup_u)){
+ print( d[which(d$氏名 == dup_u[i]), ] )
+ cat("---------------------------\n")
+ }
名字 名前 年齢 氏名
1 伊東 二郎 52 伊東.二郎
9 伊東 二郎 35 伊東.二郎
16 伊東 二郎 22 伊東.二郎
---------------------------
名字 名前 年齢 氏名
3 遠藤 太郎 53 遠藤.太郎
10 遠藤 太郎 23 遠藤.太郎
---------------------------
名字 名前 年齢 氏名
12 工藤 吾郎 53 工藤.吾郎
15 工藤 吾郎 53 工藤.吾郎
---------------------------
これで、重複のあった対象の1つ目のものも確認できるようになりました。
コメント
コメントを投稿