Tidyなデータ処理

Kanazawa.R #1

伊東宏樹

2024-06-29

[CC-BY-SA]

内容

  • Tidy data(整然データ)とは

  • tidyverseの紹介(一部)

    • tidyrパッケージ

    • dplyrパッケージ

  • さらに知るには(参考情報)

Tidy data(整然データ)

解析で扱いやすいデータ形式

Tidy dataの条件

  1. 個々の変数が1つの列をなす

  2. 個々の観測が1つの行をなす

  3. 個々の観測の構成単位の類型が1つの表をなす

  4. 個々の値が1つのセルをなす

(西原史暁 整然データとは何か)

Tidyでないデータ

=Messy data(雑然データ)の例

地点 6時 12時 18時
札幌
東京
福岡

(西原史暁 整然データとは何か)

Tidyなデータ(整然データ)

地点 時刻 天気
札幌 6時
札幌 12時
札幌 18時
東京 6時
東京 12時
東京 18時
福岡 6時
福岡 12時
福岡 18時

現実にはtidyでないデータが多い

環境省「越前岬測定所の2009年における空間放射線量率測定結果(1時間値)の確定値」https://housyasen.env.go.jp/csv/181_AB_01s_2009.csv

→ まずはデータの整形 (tidy化)

データサイエンスのプロセス

(Wickham H. et al. (2023) R for Data Science (2nd ed.), CC-BY-NC-ND 3.0)

tidyverse

データ処理に一貫性をもって使えるパッケージ群、あるいはそのコアとなるパッケージを集めたメタパッケージ

library(tidyverse)
── Attaching core tidyverse packages ────────────── tidyverse 2.0.0 ──
✔ dplyr     1.1.4     ✔ readr     2.1.5
✔ forcats   1.0.0     ✔ stringr   1.5.1
✔ ggplot2   3.5.1     ✔ tibble    3.2.1
✔ lubridate 1.9.3     ✔ tidyr     1.3.1
✔ purrr     1.0.2     
── Conflicts ──────────────────────────────── tidyverse_conflicts() ──
✖ dplyr::filter() masks stats::filter()
✖ dplyr::lag()    masks stats::lag()
ℹ Use the conflicted package (<http://conflicted.r-lib.org/>) to force all conflicts to become errors

tidyrパッケージ

  • データの変形

  • tidy化

Tidy化の例

例として「世界銀行による各国の人口データ」を整形する

data(world_bank_pop)
print(world_bank_pop, width = 66)
# A tibble: 1,064 × 20
   country indicator        `2000`  `2001`  `2002`  `2003`  `2004`
   <chr>   <chr>             <dbl>   <dbl>   <dbl>   <dbl>   <dbl>
 1 ABW     SP.URB.TOTL      4.16e4 4.20e+4 4.22e+4 4.23e+4 4.23e+4
 2 ABW     SP.URB.GROW      1.66e0 9.56e-1 4.01e-1 1.97e-1 9.46e-2
 3 ABW     SP.POP.TOTL      8.91e4 9.07e+4 9.18e+4 9.27e+4 9.35e+4
 4 ABW     SP.POP.GROW      2.54e0 1.77e+0 1.19e+0 9.97e-1 9.01e-1
 5 AFE     SP.URB.TOTL      1.16e8 1.20e+8 1.24e+8 1.29e+8 1.34e+8
 6 AFE     SP.URB.GROW      3.60e0 3.66e+0 3.72e+0 3.71e+0 3.74e+0
 7 AFE     SP.POP.TOTL      4.02e8 4.12e+8 4.23e+8 4.34e+8 4.45e+8
 8 AFE     SP.POP.GROW      2.58e0 2.59e+0 2.61e+0 2.62e+0 2.64e+0
 9 AFG     SP.URB.TOTL      4.31e6 4.36e+6 4.67e+6 5.06e+6 5.30e+6
10 AFG     SP.URB.GROW      1.86e0 1.15e+0 6.86e+0 7.95e+0 4.59e+0
# ℹ 1,054 more rows
# ℹ 13 more variables: `2005` <dbl>, `2006` <dbl>, `2007` <dbl>,
#   `2008` <dbl>, `2009` <dbl>, `2010` <dbl>, `2011` <dbl>,
#   `2012` <dbl>, `2013` <dbl>, `2014` <dbl>, `2015` <dbl>,
#   `2016` <dbl>, `2017` <dbl>

こうしたい

country year SP.URB.TOTL SP.URB.GROW SP.POP.TOTL SP.POP.GROW
ABW 2000 41625 1.66 89101 2.54
ABW 2001 42025 0.956 90691 1.77
  : :   :   :   :   :  
ABW 2017 45648 0.772 105439 0.537
AFE 2000 115551653 3.60 401600588 2.58
  : :   :   :   :   :  
ZWE 2017 4755312 1.86 14751101 2.04

pivot_longer

2000から2017までの列を、各年のデータが縦に並ぶように変形する(year列に年が入る)

pop_long <- world_bank_pop |>
  pivot_longer(cols = `2000`:`2017`, names_to = "year")
print(pop_long)
# A tibble: 19,152 × 4
   country indicator   year  value
   <chr>   <chr>       <chr> <dbl>
 1 ABW     SP.URB.TOTL 2000  41625
 2 ABW     SP.URB.TOTL 2001  42025
 3 ABW     SP.URB.TOTL 2002  42194
 4 ABW     SP.URB.TOTL 2003  42277
 5 ABW     SP.URB.TOTL 2004  42317
 6 ABW     SP.URB.TOTL 2005  42399
 7 ABW     SP.URB.TOTL 2006  42555
 8 ABW     SP.URB.TOTL 2007  42729
 9 ABW     SP.URB.TOTL 2008  42906
10 ABW     SP.URB.TOTL 2009  43079
# ℹ 19,142 more rows

パイプ演算子

|>’ : 結果の値を次の関数の第1引数として送る

標準のパイプ演算子が導入される前は

%>%’ : magrittrパッケージのパイプ演算子

pivot_wider

indicator列の値を変数名に、value列を値として列に展開する

pop_tidy <- pop_long |>
  pivot_wider(names_from = indicator, values_from = value)
print(pop_tidy)
# A tibble: 4,788 × 6
   country year  SP.URB.TOTL SP.URB.GROW SP.POP.TOTL SP.POP.GROW
   <chr>   <chr>       <dbl>       <dbl>       <dbl>       <dbl>
 1 ABW     2000        41625      1.66         89101       2.54 
 2 ABW     2001        42025      0.956        90691       1.77 
 3 ABW     2002        42194      0.401        91781       1.19 
 4 ABW     2003        42277      0.197        92701       0.997
 5 ABW     2004        42317      0.0946       93540       0.901
 6 ABW     2005        42399      0.194        94483       1.00 
 7 ABW     2006        42555      0.367        95606       1.18 
 8 ABW     2007        42729      0.408        96787       1.23 
 9 ABW     2008        42906      0.413        97996       1.24 
10 ABW     2009        43079      0.402        99212       1.23 
# ℹ 4,778 more rows

dplyrパッケージ

データの集計・抽出・並べ替えなど

以下、dplyrパッケージの主要な関数を紹介します

mutate —新しい列をつくる—

SP.POP.TOTLSP.URB.TOTLの差をpop_non_urbという新しい変数にする

pop_new <- pop_tidy |>
  mutate(pop_non_urb = SP.POP.TOTL - SP.URB.TOTL)
pop_new
# A tibble: 4,788 × 7
   country year  SP.URB.TOTL SP.URB.GROW SP.POP.TOTL SP.POP.GROW
   <chr>   <chr>       <dbl>       <dbl>       <dbl>       <dbl>
 1 ABW     2000        41625      1.66         89101       2.54 
 2 ABW     2001        42025      0.956        90691       1.77 
 3 ABW     2002        42194      0.401        91781       1.19 
 4 ABW     2003        42277      0.197        92701       0.997
 5 ABW     2004        42317      0.0946       93540       0.901
 6 ABW     2005        42399      0.194        94483       1.00 
 7 ABW     2006        42555      0.367        95606       1.18 
 8 ABW     2007        42729      0.408        96787       1.23 
 9 ABW     2008        42906      0.413        97996       1.24 
10 ABW     2009        43079      0.402        99212       1.23 
# ℹ 4,778 more rows
# ℹ 1 more variable: pop_non_urb <dbl>

select —列を抽出する—

pop_newから、country, year, SP.POP.TOTL, SP.URB.TOTL, pop_non_urbの5つの列(変数)を残す

pop_new |>
  select(country, year, SP.POP.TOTL, SP.URB.TOTL, pop_non_urb)
# A tibble: 4,788 × 5
   country year  SP.POP.TOTL SP.URB.TOTL pop_non_urb
   <chr>   <chr>       <dbl>       <dbl>       <dbl>
 1 ABW     2000        89101       41625       47476
 2 ABW     2001        90691       42025       48666
 3 ABW     2002        91781       42194       49587
 4 ABW     2003        92701       42277       50424
 5 ABW     2004        93540       42317       51223
 6 ABW     2005        94483       42399       52084
 7 ABW     2006        95606       42555       53051
 8 ABW     2007        96787       42729       54058
 9 ABW     2008        97996       42906       55090
10 ABW     2009        99212       43079       56133
# ℹ 4,778 more rows

filter —条件にあう行を抽出する—

前の結果から、yearが2017かつSP.POP.TOTLが1億以上の行を抽出する

pop_new |>
  select(country, year, SP.POP.TOTL, SP.URB.TOTL, pop_non_urb) |>
  filter(year == 2017, SP.POP.TOTL >= 1e+8)
# A tibble: 58 × 5
   country year  SP.POP.TOTL SP.URB.TOTL pop_non_urb
   <chr>   <chr>       <dbl>       <dbl>       <dbl>
 1 AFE     2017    632746296   223732118   409014178
 2 AFW     2017    431138704   198494008   232644696
 3 ARB     2017    423664839   247298631   176366208
 4 BGD     2017    161793964    58016080   103777884
 5 BRA     2017    208504960   179958546    28546414
 6 CEB     2017    102740078    63954111    38785967
 7 CHN     2017   1396215000   809246214   586968786
 8 EAP     2017   2080968782  1138074091   942894691
 9 EAR     2017   3252529883  1453160846  1799369037
10 EAS     2017   2327134580  1354328520   972806060
# ℹ 48 more rows

arrange —行を並べ替える—

さらにSP.POP.TOTLで降順に並べ替える

pop_new |>
  select(country, year, SP.POP.TOTL, SP.URB.TOTL, pop_non_urb) |>
  filter(year == 2017, SP.POP.TOTL >= 1e+8) |>
  arrange(desc(SP.POP.TOTL))
# A tibble: 58 × 5
   country year  SP.POP.TOTL SP.URB.TOTL pop_non_urb
   <chr>   <chr>       <dbl>       <dbl>       <dbl>
 1 WLD     2017   7578157615  4147418821  3430738794
 2 IBT     2017   6401367406  3189667379  3211700027
 3 LMY     2017   6322861019  3131897864  3190963155
 4 MIC     2017   5679375318  2922044655  2757330663
 5 IBD     2017   4776473096  2596413659  2180059437
 6 EAR     2017   3252529883  1453160846  1799369037
 7 LMC     2017   3225575822  1324700256  1900875566
 8 UMC     2017   2453799496  1597344399   856455097
 9 EAS     2017   2327134580  1354328520   972806060
10 LTE     2017   2286564636  1407844671   878719965
# ℹ 48 more rows

summarise(summarize) —集計する—

pop_tidyについてcountryごとにSP.POP.TOTLの平均を求め、mean_popという変数に入れる

pop_tidy |>
  group_by(country) |>
  summarise(mean_pop = mean(SP.POP.TOTL))
# A tibble: 266 × 2
   country   mean_pop
   <chr>        <dbl>
 1 ABW         98149.
 2 AFE     508006585.
 3 AFG      27344241.
 4 AFW     344981567.
 5 AGO      22558192 
 6 ALB       2958262.
 7 AND         73219.
 8 ARB     352168137.
 9 ARE       6582948.
10 ARG      40454868.
# ℹ 256 more rows

グラフ化

さらに上位10地域を棒グラフに

pop_tidy |>
  group_by(country) |>
  summarise(mean_pop = mean(SP.POP.TOTL)) |>
  arrange(desc(mean_pop)) |>
  slice(1:10) |>
  ggplot(aes(x = country, y = mean_pop)) +
  geom_bar(stat = "identity")

グラフ化

その他、よくつかう関数

  • bind_rows: データセットを縦につなげる

  • bind_cols: データセットを横につなげる

  • *_join: 2つのデータセットをキー列を参照して結合する

    • inner_join, left_join, right_join, full_join, …

さらに知るには