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

#R初心者におすすめのパッケージ
[R初心者はこれを見ろ！便利なパッケージまとめ！入門編](https://qiita.com/Naka-u/items/ac965d417fd3aed22ca5)の続きです。
ちなみに、前回は`data.table`や`dplyr`(`select` `filter` `mutate` `summarise` `group_by`)、重複削除の`distinct`について書かせていただきました。

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

##dplyr
まず、`inner_join`と`anti_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_join` は`data 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_join`は`inner_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
```



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