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

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

【R】パイプ表現中の繰り返し処理に便利な関数「map」

パイプと相性の良い繰り返し処理

はじめに

今回はパイプ表現(%>%)の中で繰り返し処理を実行する時に便利な関数であるmap関数の使い方を紹介します。tibblegroup_nestと組み合わせて使うと柔軟にデータ処理できるためおすすめです。ぜひfor文から卒業してmapを使いこなせるようになってください。

 

map関数とは

map関数は様々な型タイプのデータに対して繰り返し処理を実行できる関数です。purrrパッケージに含まれている関数なのでこのパッケージをインストールして呼び出せば使えます。またこのパッケージ自体がtidyverseシリーズに含まれているのでtidyverseパッケージをインストールして呼び出しても使うことができます。基本的な使い方は以下の通りです。

library(purrr) 
map( 変数, 関数)
  • 変数 : 繰り返し処理の中に入れる変数
  • 関数: 繰り返し実施したい関数

具体例

ベクトルの中身に関して繰り返し処理する

まず1つ目の例はfor文とほとんど同じ使い方となるベクトルの中身を繰り返す例です。今回は平均値を1から10まで移動させながら標準偏差1の正規分布からランダムに10個の値をとってくるという処理を実施します。

library(purrr)
set.seed(1)
map(1:10, rnorm, n = 10, sd = 1)  

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

[[1]]
 [1] 0.3735462 1.1836433 0.1643714 2.5952808 1.3295078
 [6] 0.1795316 1.4874291 1.7383247 1.5757814 0.6946116

[[2]]
 [1]  3.5117812  2.3898432  1.3787594 -0.2146999  3.1249309
 [6]  1.9550664  1.9838097  2.9438362  2.8212212  2.5939013

[[3]]
 [1] 3.918977 3.782136 3.074565 1.010648 3.619826 2.943871
 [7] 2.844204 1.529248 2.521850 3.417942

[[4]]
 [1] 5.358680 3.897212 4.387672 3.946195 2.622940 3.585005
 [7] 3.605710 3.940687 5.100025 4.763176

[[5]]
 [1] 4.835476 4.746638 5.696963 5.556663 4.311244 4.292505
 [7] 5.364582 5.768533 4.887654 5.881108

[[6]]
 [1] 6.398106 5.387974 6.341120 4.870637 7.433024 7.980400
 [7] 5.632779 4.955865 6.569720 5.864945

[[7]]
 [1] 9.401618 6.960760 7.689739 7.028002 6.256727 7.188792
 [7] 5.195041 8.465555 7.153253 9.172612

[[8]]
 [1] 8.475510 7.290054 8.610726 7.065902 6.746367 8.291446
 [7] 7.556708 8.001105 8.074341 7.410479

[[9]]
 [1]  8.431331  8.864821 10.178087  7.476433  9.593946
 [6]  9.332950 10.063100  8.695816  9.370019  9.267099

[[10]]
 [1]  9.457480 11.207868 11.160403 10.700214 11.586833
 [6] 10.558486  8.723408  9.426735  8.775387  9.526599

今回のコードにおける各引数の役割は以下の通りです。

  • 1:10 : 変数(1から10までの数列)
  • rnorm : 関数(正規分布から値を取り出す)
  • n = 10, sd = 1: rnorm関数の引数(サンプル数10、標準誤差1)

ちなみにmapで出力される結果はリスト形式になっています。ただ、map_dfでデータフレームとして出力させたり、map_dblで数字として出力させたりすることができます。

今回のコードの動作イメージは以下のようになります。
 

map, ベクトルに対する処理  

 

データフレームの特定の列に関して繰り返し処理する

2つ目の使い方はデータフレームの特定の列の中身を繰り返し処理する使い方です。この時、mutateと一緒に使うことで繰り返し処理した結果を新しい列として追加することができます。今回は1から10までの数字を2倍にする処理をしてその結果を新しい列として追加するという処理をやってみます。今回はコードを簡潔に書くために自作関数を定義し、それを使います。

library(tidyverse)
f = function(x){x*2} #値を2倍にする関数を定義する 
data.frame(number = 11:20) %>%  # 11から20までの値をnumber列として持つデータフレームを作成
  mutate(double= map(number, f))    # 作成したnumber列に対して定義したf関数を1つずつ繰り返し適応 

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

number double
1 11 22
2 12 24
3 13 26
4 14 28
5 15 30
6 16 32
7 17 34
8 18 36
9 19 38
10 20 40

今回のコードではまずfunction関数を用いて、入力した値を2倍にして返す自作関数を定義しています。 ちなみに自作関数についてはこちらの記事を参考にしてみてください。

www.bioinfoblog.com

そして1から10までの値をnumber列として持つデータフレームを作成し、そこにmutate関数でdouble列を追加しています。このdouble列の中身はmap関数を適応して処理しており、処理内容はnumber列の中身をあらかじめ定義したfという自作関数に代入して2倍にして返しています。
ちなみにデータフレームの作成から列の追加までの間はパイプ演算子を使って処理をそのまま繋げています。

この使い方のイメージは以下の通りです

map dataframe イメージ

 

map関数の動作イメージ

動作のイメージ概要を図にまとめると次の図のようになります。

 

map イメージ

 

まとめ

今回はRでの繰り返し処理に使える関数mapを紹介しました。

この関数はパイプ演算子との相性が良く、パイプ演算子で繋げて処理している最中にも繰り返し処理を実施できるため重宝します。データを整えながら最終的な統計解析などの処理までをパイプで繋げておこないたい場合はこれを使いましょう!