LoginSignup
1
4

More than 5 years have passed since last update.

R初心者はこれを見ろ!便利なパッケージまとめ!入門編②

Posted at

R初心者におすすめのパッケージ

R初心者はこれを見ろ!便利なパッケージまとめ!入門編の続きです。
ちなみに、前回はdata.tabledplyr(select filter mutate summarise group_by)、重複削除のdistinctについて書かせていただきました。

今回の内容

今回もdplyrについて説明していきます。
inner_join (%in%も触れます)
anti_join
あたりを説明します。
変数加工に便利なので、「知らない!」という方は、お読みいただければと存じます。

dplyr

まず、inner_joinanti_joinから。
tableは、顧客ID別の購入レコードとご理解ください。
ターゲットにしているブランドがABCであり、ABCの購入週にpurchase_flg : 1が立っているデータです。
このようなデータから、2回以上「ABC」を購入した顧客のデータだけ抽出したいとします。
このような時にinner_joinは便利です。

> table
   ID Weeks Brand
1   A     1   ABC
2   A     2   ABC
3   A     3   DEF
4   A     4   ABC
5   B     1   DEF
6   B     2   DEF
7   B     3   DEF
8   B     4   ABC
9   C     1   ABC
10  C     2   GHI
11  C     3   ABC
12  C     4   GHI
13  D     1   GHI
14  D     2   GHI
15  D     3   ABC
16  D     4   DEF

手順としては、2回以上購入のIDを始めに抽出します。

#2回以上購入の顧客IDをまず抜き出します
> over2 <- table %>%                 #%>%はパイプ処理と呼ばれ、このように連続で変数加工ができます
   dplyr::filter(Brand == "ABC") %>%    #ABC購入レコードだけにします
   dplyr::group_by(ID) %>%          #以下をID別に処理します   
   dplyr::summarise(freq = n()) %>%     #freqという列名で、ID別にレコード数を数えます。n()で行数をカウントできます
   dplyr::filter(freq >= 2)         #上で作った、freq列の値が2以上のレコードのみにします。

> over2                   #このように、A(3回)、C(2回)のデータができます。
# A tibble: 2 x 2
  ID     freq
  <chr> <int>
1 A         3
2 C         2

ちなみに、summariseまでですと、以下のようなデータになります。
このデータに、freq列でフィルターを掛けていたわけです。

> over2 <- table %>%         
   dplyr::filter(Brand == "ABC") %>% 
   dplyr::group_by(ID) %>% 
   dplyr::summarise(freq = n())

> over2
# A tibble: 4 x 2
  ID     freq
  <chr> <int>
1 A         3
2 B         1
3 C         2
4 D         1

続いて、over2に二回以上の購入IDが格納されましたので、これとtableを紐づけます。
というか、tableのID列が、over2のID列と一致するレコードを抽出します

> pick_up <- table %>% 
   dplyr::inner_join(over2, by = "ID")  #tableとover2にて、ID列が共通するレコードのみにします。

> pick_up
  ID Weeks Brand purchase_flg freq
1  A     1   ABC            1    3
2  A     2   ABC            1    3
3  A     3   DEF            0    3
4  A     4   ABC            1    3
5  C     1   ABC            1    2
6  C     2   GHI            0    2
7  C     3   ABC            1    2
8  C     4   GHI            0    2

見ての通り、inner_joinを使えば一瞬です。
by = 列名にて、列名を指定し、指定した列名に共通する値を持つレコードが残ります。
もし、列名が異なる場合は、以下のようにします。

> colnames(over2)[1] <- c("MonitorCD")  #over2の1列目の列名を MonitorCDに変えています。
> over2                  #無事、列名が変わっています
# A tibble: 2 x 2
  MonitorCD  freq
  <chr>     <int>
1 A             3
2 C             2

> pick_up <- table %>% 
+   dplyr::inner_join(over2, by = c("ID" = "MonitorCD"))
> pick_up
  ID Weeks Brand purchase_flg freq
1  A     1   ABC            1    3
2  A     2   ABC            1    3
3  A     3   DEF            0    3
4  A     4   ABC            1    3
5  C     1   ABC            1    2
6  C     2   GHI            0    2
7  C     3   ABC            1    2
8  C     4   GHI            0    2

上記のように、by = c("A" = "B")のようにしてあげると、異なる列名でも指定できます。
また、複数の列名で共通するレコードにしたい場合は、

> pick_up <- table %>% 
   dplyr::inner_join(over2, by = c("ID" = "MonitorCD", "Weeks" = "freq"))

> pick_up
  ID Weeks Brand purchase_flg
1  A     3   DEF            0
2  C     2   GHI            0

上記のように、by = c("A", "B")と列名を複数指定します。

ちなみに、%in%という、技もあります。

> target <- c("A", "C")  
> target
[1] "A" "C"

> pick_up2 <- table[table$ID %in% target,]
> pick_up2
   ID Weeks Brand purchase_flg
1   A     1   ABC            1
2   A     2   ABC            1
3   A     3   DEF            0
4   A     4   ABC            1
9   C     1   ABC            1
10  C     2   GHI            0
11  C     3   ABC            1
12  C     4   GHI            0

inner_joindata frameでないと使えませんが、%in%は上記のようにdata frameじゃなくても使えます。
もちろん、下記のようにdata frameでも使えます。

> pick_up2 <- table[table$ID %in% over2$MonitorCD,]
> pick_up2
   ID Weeks Brand purchase_flg
1   A     1   ABC            1
2   A     2   ABC            1
3   A     3   DEF            0
4   A     4   ABC            1
9   C     1   ABC            1
10  C     2   GHI            0
11  C     3   ABC            1
12  C     4   GHI            0

このように、inner_joinとは異なり、[freq]の列は引き継がれません。
inner_joinは名前の通り、データの「統合」なのです。

anti_join

anti_joininner_joinの逆で合致しないものを残してくっつけます、

#まずはデータの確認から、(上と同じものです)
> table
   ID Weeks Brand purchase_flg
1   A     1   ABC            1
2   A     2   ABC            1
3   A     3   DEF            0
4   A     4   ABC            1
5   B     1   DEF            0
6   B     2   DEF            0
7   B     3   DEF            0
8   B     4   ABC            1
9   C     1   ABC            1
10  C     2   GHI            0
11  C     3   ABC            1
12  C     4   GHI            0
13  D     1   GHI            0
14  D     2   GHI            0
15  D     3   ABC            1
16  D     4   DEF            0

> over2
# A tibble: 2 x 2
  MonitorCD  freq
  <chr>     <int>
1 A             3
2 C             2

> pick_up <- table %>% 
   dplyr::anti_join(over2, by = c("ID" = "MonitorCD"))
> pick_up
  ID Weeks Brand purchase_flg
1  B     1   DEF            0
2  B     2   DEF            0
3  B     3   DEF            0
4  B     4   ABC            1
5  D     1   GHI            0
6  D     2   GHI            0
7  D     3   ABC            1
8  D     4   DEF            0

この通り、AでもCでもない列が残りました。
これも%in%を使って代替できます。

#!で否定することで「合致しないもの」になります
> pick_up2 <- table[!table$ID %in% over2$MonitorCD,]
> pick_up2
   ID Weeks Brand purchase_flg
5   B     1   DEF            0
6   B     2   DEF            0
7   B     3   DEF            0
8   B     4   ABC            1
13  D     1   GHI            0
14  D     2   GHI            0
15  D     3   ABC            1
16  D     4   DEF            0

本日はここまでです。
次回はtidyrspread, gatherあたりをまとめようかと思います。
もし、「こんな事できないの?」とか「こういうことが知りたい」等ありましたら、コメントいただければと思います。

1
4
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
4