Rでコマンド:データ操作に便利な「tidyr」パッケージ

Rの解析に役に立つ記事
スポンサーリンク

データのlong型やwide型への変形、欠損値やネスト構造化に便利な「tidyr」パッケージのコマンドを再確認しました。「gather」コマンドや「spread」コマンドが有名なパッケージです。

パッケージバージョンは0.7.1。windows 10のR version 3.4.1で動作を確認しています。

スポンサーリンク

パッケージのインストール

下記コマンドを実行してください。

#パッケージのインストール
install.packages("tidyr")

パッケージの読み込みとデータ例の作成

データ例「TestData」を利用しコマンドを紹介しています。

#パッケージの読み込み
library("tidyr")

###データ例の作成#####
n <- 5
set.seed(10)
TestData <- data.frame(Group = I(sample(c(paste0("Group", 1:2), NA),
                                        n, replace = TRUE)),
                          Data1 = rnorm(n),
                          Data2 = rnorm(n) + rnorm(n) + rnorm(n),
                          Data3 = sample(0:1, n, replace = TRUE),
                          Data4 = sample(LETTERS[1:26], n, replace = TRUE))
#&#30906;&#35469;
TestData

パイプ演算子「%>%」の紹介

パイプ演算子の左側のオブジェクトをパイプ演算子右側の関数の最初の引数へ渡します。利用することでコマンド記述が文法的になり内容の理解が捗ります。でもコメントの記述は大事です。

#TestData[1:2, 1]&#12434;&#19977;&#22238;&#32368;&#12426;&#36820;&#12377;
#%>%&#12434;&#20351;&#12431;&#12394;&#12356;
rep(x = TestData[1:2, 1], time = 3)
[1] "Group2" "Group1" "Group2" "Group1" "Group2" "Group1"
#%>%&#12434;&#20351;&#12358;
TestData[1:2, 1] %>% rep(time = 3)
[1] "Group2" "Group1" "Group2" "Group1" "Group2" "Group1"

データ変形コマンド

データをlong型に変形する「gather」コマンド、long型データをwide型に変形する「spread」コマンド、データをネスト構造にする「nest」コマンド、ネスト構造からデータを取り出す「unnest」コマンドの紹介です。

#&#12487;&#12540;&#12479;&#12434;long&#22411;&#12395;&#22793;&#24418;:gather&#12467;&#12510;&#12531;&#12489;
#&#20363;1:&#32080;&#26524;&#12395;&#21454;&#12417;&#12427;&#31684;&#22258;&#12434;&#25351;&#23450;
WideData <- TestData %>% gather(key = "&#12487;&#12540;&#12479;&#21517;", value = "&#32080;&#26524;", 2:4)
head(WideData)
Group Data4 &#12487;&#12540;&#12479;&#21517;       &#32080;&#26524;
1 Group2     J    Data1 -0.7539600
2 Group1     Y    Data1 -0.6058564
3 Group2     G    Data1 -0.1772105
4   &lt;NA&gt;     M    Data1  0.1706176
5 Group1     E    Data1  0.2428141
6 Group2     J    Data2  1.0316243
#&#20363;2&#65306;&#32080;&#26524;&#12395;&#21454;&#12417;&#12427;&#31684;&#22258;&#12434;&#38500;&#22806;&#12391;&#25351;&#23450;
TestData %>% gather(key = "&#12487;&#12540;&#12479;&#21517;", value = "&#32080;&#26524;",
                    -Group, -Data4) %>% head()
Group Data4 &#12487;&#12540;&#12479;&#21517;       &#32080;&#26524;
1 Group2     J    Data1 -0.7539600
2 Group1     Y    Data1 -0.6058564
3 Group2     G    Data1 -0.1772105
4   &lt;NA&gt;     M    Data1  0.1706176
5 Group1     E    Data1  0.2428141
6 Group2     J    Data2  1.0316243

#long&#22411;&#12487;&#12540;&#12479;&#12434;wide&#22411;&#12395;&#22793;&#24418;:spread&#12467;&#12510;&#12531;&#12489;
WideData %>% spread(key = "&#12487;&#12540;&#12479;&#21517;", value = "&#32080;&#26524;")
Group Data4      Data1      Data2 Data3
1 Group1     E  0.2428141  1.5199529     1
2 Group1     Y -0.6058564  0.3536115     0
3 Group2     G -0.1772105  0.6105086     0
4 Group2     J -0.7539600  1.0316243     0

#&#31684;&#22258;&#12395;&#23550;&#12377;&#12427;data.frame&#12434;list&#12408;&#20445;&#23384;(&#12493;&#12473;&#12488;&#27083;&#36896;&#21270;):nest&#12467;&#12510;&#12531;&#12489;
#&#31684;&#22258;&#12398;&#25351;&#23450;&#12399;gather&#12467;&#12510;&#12531;&#12489;&#12392;&#21516;&#12376;
NestData <- TestData %>% gather(key = "&#12487;&#12540;&#12479;&#21517;",
                                value = "&#32080;&#26524;", -Group, -Data4) %>%
  nest(-Group, .key = "list")
#&#12487;&#12540;&#12479;&#12434;&#21462;&#12426;&#20986;&#12377;
NestData[2, 2]
[[1]]
Data4 &#12487;&#12540;&#12479;&#21517;       &#32080;&#26524;
2      Y    Data1 -0.6058564
5      E    Data1  0.2428141
7      Y    Data2  0.3536115
10     E    Data2  1.5199529
12     Y    Data3  0.0000000
15     E    Data3  1.0000000

#&#12493;&#12473;&#12488;&#27083;&#36896;&#12363;&#12425;&#12487;&#12540;&#12479;&#12434;&#21462;&#12426;&#20986;&#12377;:unnest&#12467;&#12510;&#12531;&#12489;
unnest(NestData, .id = "List_No.")
Group List_No. Data4 &#12487;&#12540;&#12479;&#21517;       &#32080;&#26524;
1  Group2        1     J    Data1 -0.7539600
2  Group2        1     G    Data1 -0.1772105
3  Group2        1     J    Data2  1.0316243
4  Group2        1     G    Data2  0.6105086
5  Group2        1     J    Data3  0.0000000
6  Group2        1     G    Data3  0.0000000

損値とデータ組み合わせのコマンド

欠損値を含むデータを削除する「drop_na」コマンド、欠損値を直前に出現した値で保管する「fill」コマンド、欠損値を置換する「replace_na」コマンド、指定した列の全てを組み合わせる「expand」コマンド、存在するデータを組み合わせる「nesting」コマンド、指定したベクトルと行を全て組み合わせる「crossing」コマンドの紹介です。

#&#27424;&#25613;&#20516;&#12434;&#21547;&#12416;&#12487;&#12540;&#12479;&#12434;&#21066;&#38500;:drop_na&#12467;&#12510;&#12531;&#12489;
TestData %>% drop_na()
Group      Data1     Data2 Data3 Data4
1 Group2 -0.7539600 1.0316243     0     J
2 Group1 -0.6058564 0.3536115     0     Y
3 Group2 -0.1772105 0.6105086     0     G
5 Group1  0.2428141 1.5199529     1     E

#&#27424;&#25613;&#20516;&#12434;&#30452;&#21069;&#12395;&#20986;&#29694;&#12375;&#12383;&#20516;&#12391;&#20445;&#31649;:fill&#12467;&#12510;&#12531;&#12489;
#&#26119;&#38477;&#12398;&#35373;&#23450;:.direction&#12458;&#12503;&#12471;&#12519;&#12531;;"down","up"
TestData %>% fill(Group, .direction = "down")
Group      Data1      Data2 Data3 Data4
1 Group2 -0.7539600  1.0316243     0     J
2 Group1 -0.6058564  0.3536115     0     Y
3 Group2 -0.1772105  0.6105086     0     G
4 Group2  0.1706176 -1.7711400     0     M
5 Group1  0.2428141  1.5199529     1     E

#&#27424;&#25613;&#20516;&#12434;&#32622;&#25563;:replace_na&#12467;&#12510;&#12531;&#12489;
#factor&#12395;&#12399;&#36969;&#24540;&#12391;&#12365;&#12394;&#12356;
TestData %>% replace_na(list(Group = 3))
Group      Data1      Data2 Data3 Data4
1 Group2 -0.7539600  1.0316243     0     J
2 Group1 -0.6058564  0.3536115     0     Y
3 Group2 -0.1772105  0.6105086     0     G
4      3  0.1706176 -1.7711400     0     M
5 Group1  0.2428141  1.5199529     1     E

#&#25351;&#23450;&#12375;&#12383;&#21015;&#12398;&#20840;&#12390;&#12434;&#32068;&#12415;&#21512;&#12431;&#12379;&#12427;:expand&#12467;&#12510;&#12531;&#12489;
TestData %>% expand(Data3, Group)
# A tibble: 6 x 2
Data3  Group
&lt;int&gt;  &lt;chr&gt;
1     0 Group1
2     0 Group2
3     1 Group1
4     1 Group2

#&#23384;&#22312;&#12377;&#12427;&#12487;&#12540;&#12479;&#12434;&#32068;&#12415;&#21512;&#12431;&#12379;&#12427;:nesting&#12467;&#12510;&#12531;&#12489;
#expand&#12467;&#12510;&#12531;&#12489;&#12392;&#32068;&#12415;&#21512;&#12431;&#12379;&#12427;&#12392;&#20415;&#21033;
TestData %>% expand(nesting(Data3, Group))
# A tibble: 4 x 2
Data3      Group
1     0     Group1
2     0     Group2

#&#25351;&#23450;&#12375;&#12383;&#12505;&#12463;&#12488;&#12523;&#12392;&#34892;&#12434;&#20840;&#12390;&#32068;&#12415;&#21512;&#12431;&#12379;&#12427;:crossing&#12467;&#12510;&#12531;&#12489;
#&#30452;&#31309;&#38598;&#21512;
TestData %>% crossing(1:2, c("A", "B")) %>% head()
Group      Data1     Data2 Data3 Data4 1:2 c("A", "B")
1 Group2 -0.7539600 1.0316243     0     J   1           A
2 Group2 -0.7539600 1.0316243     0     J   1           B
3 Group2 -0.7539600 1.0316243     0     J   2           A
4 Group2 -0.7539600 1.0316243     0     J   2           B
5 Group1 -0.6058564 0.3536115     0     Y   1           A
6 Group1 -0.6058564 0.3536115     0     Y   1           B

結合と分解のコマンド

列を結合する「unite」コマンド、データ内容を列に分割する「separate」コマンド、列データを行方向に分割する「separate_rows」コマンド

#&#21015;&#12434;&#32080;&#21512;:unite&#12467;&#12510;&#12531;&#12489;
UniteData <- TestData %>% unite(UniteData, c(Data3, Data4),
                                sep = "_", remove = FALSE)
#&#30906;&#35469;
UniteData
Group      Data1      Data2 UniteData Data3 Data4
1 Group2 -0.7539600  1.0316243       0_J     0     J
2 Group1 -0.6058564  0.3536115       0_Y     0     Y
3 Group2 -0.1772105  0.6105086       0_G     0     G

#&#12487;&#12540;&#12479;&#20869;&#23481;&#12434;&#21015;&#12395;&#20998;&#21106;:separate&#12467;&#12510;&#12531;&#12489;
UniteData %>% separate(UniteData, into = c("Data3_1", "Data4_1"),
                       sep = "_", remove = FALSE)
Group      Data1      Data2 UniteData Data3_1 Data4_1 Data3 Data4
1 Group2 -0.7539600  1.0316243       0_J       0       J     0     J
2 Group1 -0.6058564  0.3536115       0_Y       0       Y     0     Y
3 Group2 -0.1772105  0.6105086       0_G       0       G     0     G

#&#21015;&#12487;&#12540;&#12479;&#12434;&#34892;&#26041;&#21521;&#12395;&#20998;&#21106;:separate_rows&#12467;&#12510;&#12531;&#12489;
UniteData %>% separate_rows(UniteData, sep = "_", convert = TRUE)
Group      Data1      Data2 Data3 Data4 UniteData
1  Group2 -0.7539600  1.0316243     0     J         0
2  Group2 -0.7539600  1.0316243     0     J         J
3  Group1 -0.6058564  0.3536115     0     Y         0
4  Group1 -0.6058564  0.3536115     0     Y         Y
5  Group2 -0.1772105  0.6105086     0     G         0
6  Group2 -0.1772105  0.6105086     0     G         G

少しでも、あなたの解析が楽になりますように!!

タイトルとURLをコピーしました