一所懸命に手抜きする

デスクワークばかりのスポーツ嫌いで50歳も過ぎ、いよいよ足腰に衰えを感じつつある昨今。

R言語dplyr::distinctで簡単に重複行を削除できる。キー項目以外の項目も簡単に抽出。

 SQLの select distinct では指定した列をキーにして重複のないデータを取得できます。
 重複する行を削除するSELECT DISTINCT - 一所懸命に手抜きする
 重複行削除の際、重複判定に指定したキー列項目以外の列も取得するSQL - 一所懸命に手抜きする

 R言語でも同様のことができるのは既に書きました。
 R言語のuniqueや!duplicated で重複のないデータを取り出す - 一所懸命に手抜きする
 dplyrパッケージを使うと、もっと簡単に実現できます。

Sampleデータ作成

 当ブロクで使うサンプルデータを作成するコード保管庫|R|一所懸命に手抜きする[忍者]  に掲載したサンプル作成コードを実行すると

サンプルテーブル buyList
入荷日付 商品番号  商品名 当社原価 相手原価
20170102    12345   XA-55     3500     3500
20170103   132977    RX98     2980     3280
20170103   349401 NOK0655     2500     2500
20170103   349401 NOK0655     2500     2500
20170104   227291 NOK2355     3500    35000
20170104   227291 NOK2355     3500    35000
20170104   349401 NOK0655     2500     2500
20170105  5288923  JJ2CAN     6000     6200
20170105   132977    RX98     2780     2980

という架空の商品購買データができます。

dplyr パッケージ の distinct()

 この購買履歴データから重複を除くためにdistinct()を使ってみます。
 データフレームを加工するのに簡潔なコードが書けてかつ高速なのがdplyrパッケージ CRAN - Package dplyr です。その中のdistinct()関数です。

library("dplyr")
distinct(重複判定する項目(), .keep_all = FALSE) 

 distinct()は重複判定するキー項目(群)を与えると、キー項目が重複するデータは初出を残し、二回目以降を削除します
 .keep_all = FALSE とすると、キー項目だけが戻り値となります。
 .keep_all = TRUE  とすると、キーでない項目も含めて全項目が戻り値となります。

.keep_all = FALSE

buyList %>% distinct(商品番号,.keep_all=FALSE)
##  商品番号
##1    12345
##2   132977
##3   349401
##4   227291
##5  5288923

 これは SQL における SELECT DISTINCT の結果と同じでキー項目だけを返しています。

.keep_all = TRUE

buyList %>% distinct(商品番号,.keep_all=TRUE)
##  入荷日付 商品番号  商品名 当社原価 相手原価
##1 20170102    12345   XA-55     3500     3500
##2 20170103   132977    RX98     2980     3280
##3 20170103   349401 NOK0655     2500     2500
##4 20170104   227291 NOK2355     3500    35000
##5 20170105  5288923  JJ2CAN     6000     6200

 この例では、商品番号が重複しないように抽出されていますが、重複判定に用いたキー項目以外の全データも返しています。

戻り値として必要な項目を選択するには

 キー項目だけでは足りないけれど全項目は必要ないという場合がほとんどでしょう。
 .keep_all = TRUEを指定すると全列を返すのですから、その返り値から必要な項目を抜粋すれば良いでしょう。

  buyList %>% distinct(商品番号,.keep_all=TRUE) %>%
  subset(,c(商品番号,商品名))
##  商品番号  商品名
##1    12345   XA-55
##2   132977    RX98
##3   349401 NOK0655
##4   227291 NOK2355
##5  5288923  JJ2CAN

 %>% (パイプ演算子)は左の処理結果を右の関数の第一引数として引き渡しています。
 これを利用して、distinct()の戻り値全列から、subsetで 商品番号 商品名 を抽出しています。

[2017.1.22追記]dplyrを使うんだから

 Kankamさんよりご指摘いただきましたが、せっかくdplyrを使っているので標準関数subsetの代わりにdplyr::selectを使うと

  buyList %>% distinct(商品番号,.keep_all=TRUE) %>%
  select(商品番号,商品名)
##  商品番号  商品名
##1    12345   XA-55
##2   132977    RX98
##3   349401 NOK0655
##4   227291 NOK2355
##5  5288923  JJ2CAN

となります。表記方法もこちらの方が楽な上、処理速度も多少速い気がします。

dplyr注意

ただし、今回は本来の意図からして不要ですが、 dplyrはdata.frameから1列のみをselect抽出するとvectorで返すようですから、それを回避するためには dplyr::tbl_df を通す必要があります。

キー項目の意味に注意

 この記事ではキー項目ということばを検索に用いる項目という意味で使っています。データベースでキー設定がなされている項目と言う意味ではありません。

Hello, everyone.
Some accesses were from foreign countries.
Thank you!
In R language,
we can remove duplicated rows and get unique/distinct rows from a dataframe ,using dplyr::distinct.
In SQL,SELECT DISTINCT returns only distinct columns.
In R languages,similar function unique also returns only distinct columns.
dplyr::distinct can extract not only distinct columns but any columns we want.