統計プログラムRの勉強日記

Rに関して勉強してきたことを紹介します

【R】select関数をもっと使いこなす!ヘルパー関数の紹介

select関数応用タイトル

はじめに

今回はdplyrパッケージのselect関数をもっと効率よく使いこなすためのヘルパー関数について紹介したいと思います。select関数はデータフレームから任意の列を選択して取り出す関数です。この関数を使いこなすにはヘルパー関数を使いこなす必要があります。ぜひこの記事で列を自由自在に取捨選択できるようになってください。 ちなみにselect関数の基本的な使い方は以下の記事にまとめましたのでよろしければ参考にして下さい。

www.bioinfoblog.com

ヘルパー関数一覧

ヘルパー関数はある関数を補強するために使われる関数です。今回はselect関数の機能を補強してくれる関数を紹介します。 今回紹介する関数は以下の通りです。

  • start_with():列名の接頭語で取捨選択(列名の頭にある共通の文字列などを認識させて選択)
  • ends_with():列名の接尾語で取捨選択(列名の後ろにある共通の文字列などを認識させて選択)
  • contains():指定した文字列が含まれる列を取捨選択
  • num_range():列名に通し番号がついている場合に特定の数字範囲を指定して取捨選択
  • one_of():文字列のどれかに一致する列を取捨選択
  • everything():すべての列を取捨選択
  • matches():正規表現で列を取捨選択

start_with()

start_with()関数は列名の頭にある文字列を指定することができます。共通の文字列が列名の頭についているときはこの関数を使って一気に指定することができます。
今回は具体例としてtidyrパッケージの中にあるデータセットである relig_income から 「$で始まる列」を選択したいと思います。

library(tidyverse)
data = tidyr::relig_income
select(data, starts_with("$"))

出力される結果の頭10行はこんな感じになります。(クリックで表示)

$10-20k $20-30k $30-40k $40-50k $50-75k $75-100k $100-150k
1 34 60 81 76 137 122 109
2 27 37 52 35 70 73 59
3 21 30 34 33 58 62 39
4 617 732 670 638 1116 949 792
5 14 15 11 10 35 21 17
6 869 1064 982 881 1486 949 723
7 9 7 9 11 34 47 48
8 244 236 238 197 223 131 81
9 27 24 24 21 30 15 11
10 19 25 25 30 95 69 87

end_with()

end_with()関数は列名の末尾にある文字列を指定することができます。共通の文字列が列名の末尾についているときはこの関数を使って一気に指定することができます。
今回は具体例としてdplyrパッケージの中にあるデータセットである starwars から 「colorで終わる列」を選択したいと思います。

library(dplyr)
data = dplyr::starwars
select(data, name, ends_with("color"))

出力される結果の頭10行はこんな感じになります。(クリックで表示)

name hair_color skin_color eye_color
Luke Skywalker blond fair blue
C-3PO NA gold yellow
R2-D2 NA white, blue red
Darth Vader none white yellow
Leia Organa brown light brown
Owen Lars brown, grey light blue
Beru Whitesun lars brown light blue
R5-D4 NA white, red red
Biggs Darklighter black light brown
Obi-Wan Kenobi auburn, white fair blue-gray

contains()

contains()関数は列名に含まれている文字列を指定することができます。特定の文字列が共通して列名に入っている場合はこの関数で一気に指定することができます。start_withend_withは列名の最初や最後の文字列を指定できますが、列名の両端ではなく、間の中途半端な所に共通する文字列がある場合はこちらを使うと良いです。
今回は具体例として適当に作ったデータフレームから「record」という文字列が列名に含まれる列を取り出したいと思います。

library(dplyr)
library(magrittr)
data = as.data.frame(cbind(LETTERS[1:5], matrix(rnorm(20), ncol = 4))) %>% 
  set_colnames(c("SAMPLE", "A_record_before", "A_record_after", "B_record_before", "B_record_after"))
select(data, contains("record"))

出力される結果はこんな感じになります。(クリックで表示)

A_record_before A_record_after B_record_before B_record_after
-0.102787727 -0.394289954 -0.25336168 0.364581962
0.387671612 -0.059313397 0.696963375 0.768532925
-0.053805041 1.100025372 0.556663199 -0.112346212
-1.377059557 0.763175748 -0.688755695 0.881107726
-0.414994563 -0.164523596 -0.707495157 0.39810588

ここでstart_withend_withcontains 関数について列名のどこを参照しているのかを図にまとめたいと思います。これらの関数で参照している文字列は以下の通りです。 start_with end_with contains

num_range()

num_range()関数は列名に通し番号などが付いている場合に特定の番号範囲を指定することができます。全部の範囲ではなく特定の範囲に絞って列を選択したい時はstart_withではなくこちらの関数を使うことになります。
ここでは具体例としてtidyrパッケージのbillboardデータから artist 列と wk8からwk12 までの列を選択するコードを紹介します。(billboardデータにはwk1からwk76までの列があります。)

library(dplyr)
data = tidyr::billboard
select(data, artist, num_range(prefix = "wk", range = 8:12))

出力される結果の頭10行はこんな感じになります。(クリックで表示)

artist wk8 wk9 wk10 wk11 wk12
2 Pac NA NA NA NA NA
2Ge+her NA NA NA NA NA
3 Doors Down 53 51 51 51 51
3 Doors Down 59 62 61 61 59
504 Boyz 49 53 57 64 70
980 2 3 6 7 22
A*Teens NA NA NA NA NA
Aaliyah 38 38 36 37 37
Aaliyah 14 12 10 9 8
Adams, Yolanda 58 57 59 66 68

この関数のイメージは以下の通りです。 num_range

one_of()

one_of()関数は文字列ベクトルを用いて列を指定することができます。列名を列挙した文字列ベクトルをあらかじめ作成している時はこの関数を使うことでベクトルの中身で列を指定することができます。
select関数では第2引数以降で列名を列挙するときにダブルクオーテーションで列名を囲う必要がありません。そのため文字列なのかオブジェクト(定義した変数)なのかこの関数内で判断することができません。このことにより列名を代入したオブジェクトを本来であれば第2引数以降で指定することができないことになっています。しかしここで紹介したone_of()関数を使えばあらかじめ列名を列挙したオブジェクトを利用して列を選択できるようになるのです。
ここではwk1からwk5という文字列を格納した candidate 変数を作成し、この変数を使って先ほどの billboard データから列を選択したいと思います。

library(dplyr)
data = tidyr::billboard
candidates = paste0("wk", 1:5)
select(data, artist, one_of(candidates))

出力される結果の頭10行はこんな感じになります。(クリックで表示)

artist wk1 wk2 wk3 wk4 wk5
2 Pac 87 82 72 77 87
2Ge+her 91 87 92 NA NA
3 Doors Down 81 70 68 67 66
3 Doors Down 76 76 72 69 67
504 Boyz 57 34 25 17 17
980 51 39 34 26 26
A*Teens 97 97 96 95 100
Aaliyah 84 62 51 41 38
Aaliyah 59 53 38 28 21
Adams, Yolanda 76 76 74 69 68

one_of ちなみにこの関数では文字列ベクトルは1つだけでなく複数のベクトルを用いることができます。

everything()

everything()関数は全ての列を指定する関数です。列の取捨選択ではあまり活躍しませんが、列の並び替えなどをおこなう際には役立ちます。
今回は relig_income データを religion, Don't know/refused をデータの左側に並び替えたいと思います。

library(tidyverse)
data = tidyr::relig_income
select(data, religion, `Don't know/refused`, everything())

出力される結果の頭10行はこんな感じになります。(クリックで表示)

religion Don't know/refused <$10k $10-20k $20-30k $30-40k $40-50k $50-75k $75-100k $100-150k >150k
Agnostic 96 27 34 60 81 76 137 122 109 84
Atheist 76 12 27 37 52 35 70 73 59 74
Buddhist 54 27 21 30 34 33 58 62 39 53
Catholic 1489 418 617 732 670 638 1116 949 792 633
Don?ft know/refused 116 15 14 15 11 10 35 21 17 18
Evangelical Prot 1529 575 869 1064 982 881 1486 949 723 414
Hindu 37 1 9 7 9 11 34 47 48 54
Historically Black Prot 339 228 244 236 238 197 223 131 81 78
Jehovah's Witness 37 20 27 24 24 21 30 15 11 6
Jewish 162 19 19 25 25 30 95 69 87 151

matches()

matches()関数は正規表現で取捨選択する列を指定することができます。普通にselect関数を使うとデータフレームの列名と全く同じ列名でないと選択できませんが、この関数を使うことで列名を曖昧に指定することができます。またこの関数が今回紹介するヘルパー関数の中では最も柔軟に列を取捨選択できる関数だと思います。
今回は billboard データから列名が a, t, d で始まる列を選択したいと思います。

library(tidyverse)
data = tidyr::billboard
select(data, matches("^[atd]"))

出力される結果の頭10行はこんな感じになります。(クリックで表示)

artist track date.entered
2 Pac Baby Don't Cry (Keep... 2000/2/26
2Ge+her The Hardest Part Of ... 2000/9/2
3 Doors Down Kryptonite 2000/4/8
3 Doors Down Loser 2000/10/21
504 Boyz Wobble Wobble 2000/4/15
980 Give Me Just One Nig... 2000/8/19
A*Teens Dancing Queen 2000/7/8
Aaliyah I Don't Wanna 2000/1/29
Aaliyah Try Again 2000/3/18
Adams, Yolanda Open My Heart 2000/8/26

まとめ

今回はselect関数のヘルパー関数を紹介しました。列の取捨選択をより便利にしてくれるこれらのヘルパー関数を駆使してデータ解析頑張りましょう!