読者です 読者をやめる 読者になる 読者になる

一所懸命に手抜きする

監査の仕事をしています。ITを利用し、良い意味で「手抜き」することは効率化と精度アップに役立つと思うんです。部下への引き継ぎのためにまずは諸々頭から引っ張り出そうとブログを始めました。

[ Main ]  [ 別館 ]
当ブログで取り上げられている事案やデータベース、人物等はすべてフィクションです。

R言語のuniqueや!duplicated で重複のないデータを取り出す

 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 SQL,SELECT DISTINCT returns only distinct columns.
In R languages,similar function unique also returns only distinct columns.
!duplicated can extract unique/distinct rows with full columns.
広告を非表示にする