SQLの select distinct では指定した列をキーにして重複のないデータを取得できます。
重複する行を削除するSELECT DISTINCT - 一所懸命に手抜きする
重複行削除の際、重複判定に指定したキー列項目以外の列も取得するSQL - 一所懸命に手抜きする
ではR言語で同様のことをするにはどうすればよいのでしょう。
Sampleデータ作成
当ブロクで使うサンプルデータを作成するコード保管庫|R|一所懸命に手抜きする[忍者] に掲載したサンプル作成コードを実行すると
buyList ## 入荷日付 商品番号 商品名 当社原価 相手原価 ##1 20170102 12345 XA-55 3500 3500 ##2 20170103 132977 RX98 2980 3280 ##3 20170103 349401 NOK0655 2500 2500 ##4 20170103 349401 NOK0655 2500 2500 ##5 20170104 227291 NOK2355 3500 35000 ##6 20170104 227291 NOK2355 3500 35000 ##7 20170104 349401 NOK0655 2500 2500 ##8 20170105 5288923 JJ2CAN 6000 6200 ##9 20170105 132977 RX98 2780 2980
という架空の商品購買データができます。
重複のないデータを抽出したい
ここから、重複なくデータを抽出するにはどうすればよいでしょう。
unique関数を使うやり方
キー列が一つの場合
unique(buyList$商品番号) ##[1] "12345" "132977" "349401" "227291" "5288923"
SQL の SELECT DISTINCT と似たような結果です。
unique 関数は指定されたキー項目で重複判定し、重複を除いたキーだけを返します。キーは一つしか指定できません
この例ですと商品番号だけです。それだと何の商品かわからないので商品名もほしいのですが、このやり方ではできません。
キー列が複数の場合
df<-subset(buyList,,c(商品番号,商品名)) unique(df) ## 商品番号 商品名 ##1 12345 XA-55 ##2 132977 RX98 ##3 349401 NOK0655 ##5 227291 NOK2355 ##8 5288923 JJ2CAN
uniqueは引数を一つしかわたせないのですが列ではなくデータフレームを引数として渡せば、複数列で重複判定してくれます。
商品番号と 商品名 だけがほしいのですから、その二つだけでsubsetデータフレームを作り、unique()の引数としています。
duplicated関数を使うやり方
uniqueとは逆に重複を判定する関数としてduplicatedがあります。
こちらの方が便利なところがあります。
uniqueでは重複判定に用いたキー項目列しか抽出できませんが、!duplicatedを使うやり方だと抽出する項目を選べます。
duplicated関数は重複(TRUE)かFALSEかを返す
重複でないということは !duplicated と表せますので、
!duplicated(buyList$商品番号,) ##[1] TRUE TRUE TRUE FALSE TRUE FALSE FALSE TRUE FALSE
unique はユニークデータを直接返しましたが、duplicatedや!duplicatedは重複しているかどうかをTRUE/FALSEで返します。
データフレーム[!duplicated(重複判定列),]
ですから、!duplicated(重複していない)=TRUEだけを抜き出せば重複しないデータとなります。
buyList[!duplicated(buyList$商品番号),] ## 入荷日付 商品番号 商品名 当社原価 相手原価 ##1 20170102 12345 XA-55 3500 3500 ##2 20170103 132977 RX98 2980 3280 ##3 20170103 349401 NOK0655 2500 2500 ##5 20170104 227291 NOK2355 3500 35000 ##8 20170105 5288923 JJ2CAN 6000 6200
このやり方だと、商品番号という一つの項目で重複判定していますが、結果としては全列を返しています。
データフレーム[!duplicated(重複判定列),c(・・・)]
もしも、仕入が発生した商品一覧がほしいというならば、商品番号と商品名だけで良いでしょうから
buyList[!duplicated(buyList$商品番号),c("商品番号","商品名")] ## 商品番号 商品名 ##1 12345 XA-55 ##2 132977 RX98 ##3 349401 NOK0655 ##5 227291 NOK2355 ##8 5288923 JJ2CAN
のように返す列をc()で指定してやることもできます。
データフレーム[!duplicated(重複判定データフレーム),c(・・・)]
df<-subset(buyList,,c(商品番号,商品名)) buyList[!duplicated(df),] ## 入荷日付 商品番号 商品名 当社原価 相手原価 ##1 20170102 12345 XA-55 3500 3500 ##2 20170103 132977 RX98 2980 3280 ##3 20170103 349401 NOK0655 2500 2500 ##5 20170104 227291 NOK2355 3500 35000 ##7 20170104 349401 NOK0655 2500 2500 ##8 20170105 5288923 JJ2CAN 6000 6200 ##9 20170105 132977 RX98 2780 2980
複数列で重複判定するために、データフレームdfを作っています。dfと元のbuyListは列は違いますが行の内容は同じです。
dfで重複行となっている行はbuyListでも重複しているのですから、dfで重複判定してbuyListから判定結果を返しています。
In R languages,similar function unique also returns only distinct columns.
!duplicated can extract unique/distinct rows with full columns.