tidyr: Easily Tidy Data with spread() and gather() Functions

データ解析を容易にするデータ整形のためのパッケージ

> library(tidyr)

Attaching package: 'tidyr'
The following object is masked from 'package:magrittr':

    extract

バージョン: 0.6.1


関数名 概略
complete Complete a data frame with missing combinations of data.
expand Expand data frame to include all combinations of values
extract Extract one column into multiple columns.
extract_numeric Extract numeric component of variable.
fill Fill in missing values.
full_seq Create the full sequence of values in a vector.
gather Gather columns into key-value pairs.
nest Nest repeated values in a list-variable.
replace_na Replace missing values
separate Separate one column into multiple columns.
spread Spread a key-value pair across multiple columns.
unite Unite multiple columns into one.
unnest Unnest a list column.

complete

欠損組み合わせの補完

ref) tidyr::replace_na, tidyr::expand

Arguments

  • data
  • ...
  • fill
> (df <- dplyr::data_frame(
+   group = c(1:2, 1),
+   item_id = c(1:2, 2),
+   item_name = c("a", "b", "b"),
+   value1 = 1:3,
+   value2 = 4:6
+ ))
# A tibble: 3 × 5
  group item_id item_name value1 value2
  <dbl>   <dbl>     <chr>  <int>  <int>
1     1       1         a      1      4
2     2       2         b      2      5
3     1       2         b      3      6
> df %>% purrr::map_if(is.numeric, range)
$group
[1] 1 2

$item_id
[1] 1 2

$item_name
[1] "a" "b" "b"

$value1
[1] 1 3

$value2
[1] 4 6
> df %>% complete(group, nesting(item_id, item_name))
# A tibble: 4 × 5
  group item_id item_name value1 value2
  <dbl>   <dbl>     <chr>  <int>  <int>
1     1       1         a      1      4
2     1       2         b      3      6
3     2       1         a     NA     NA
4     2       2         b      2      5

expand / crossing / nesting

水準に応じてデータフレームを拡張する。

Arguments

  • data
  • ...
> factor(mtcars$vs)
 [1] 0 0 1 1 0 1 0 1 1 1 1 0 0 0 0 0 0 1 1 1 1 0 0 0 0 1 0 1 0 0 0 1
Levels: 0 1
> factor(mtcars$cyl)
 [1] 6 6 4 6 8 6 8 4 4 6 6 8 8 8 8 8 8 4 4 4 4 8 8 8 8 4 4 4 8 6 8 4
Levels: 4 6 8
> # 各水準同士の組み合わせからなるデータフレームを返す
> expand(mtcars, vs, cyl)
# A tibble: 6 × 2
     vs   cyl
  <dbl> <dbl>
1     0     4
2     0     6
3     0     8
4     1     4
5     1     6
6     1     8
> expand(mtcars, cyl, mpg = modelr::seq_range(x = mpg, n = 2))
# A tibble: 6 × 2
    cyl   mpg
  <dbl> <dbl>
1     4  10.4
2     4  33.9
3     6  10.4
4     6  33.9
5     8  10.4
6     8  33.9
> # cyl水準ごとにmpgの最大値と最小値を返す

extract

1つの行を複数の行に分割する

ref) unite()

Arguments

  • data... 対象データフレーム
  • col... 分割対象とする列名
  • into... 新たな列名
  • regex... 正規表現による分割の基準
  • remove
  • convert
  • ...
> (df <- data.frame(name = c("夏目 漱石", "芥川 龍之介", "太宰 治")))
         name
1   夏目 漱石
2 芥川 龍之介
3     太宰 治
> extract(data = df, col = name, into = "First")
  First
1  夏目
2  芥川
3  太宰
> extract(data = df, col = name, into = c("First", "Last"), 
+         regex = "([[:print:]]+)[[:space:]]([[:print:]]+)")
  First   Last
1  夏目   漱石
2  芥川 龍之介
3  太宰     治

extract_numeric

データから数値だけを抜き出す

> extract_numeric("100万円")
extract_numeric() is deprecated: please use readr::parse_number() instead
[1] 100
> extract_numeric("-2%")
extract_numeric() is deprecated: please use readr::parse_number() instead
[1] -2
> extract_numeric("12abc34")
extract_numeric() is deprecated: please use readr::parse_number() instead
[1] 1234
> # 明らかに数値でない場合にはエラー
> extract_numeric("神奈川県123")
extract_numeric() is deprecated: please use readr::parse_number() instead
[1] 123
> # extract_numeric("神奈川県123-456")

fill

欠損値の補完

Arguments

  • data
  • ...
  • .direction
> df <- data.frame(Month = 1:12, Year = c(2000, rep(NA, 11)))
> df %>% fill(Year)
   Month Year
1      1 2000
2      2 2000
3      3 2000
4      4 2000
5      5 2000
6      6 2000
7      7 2000
8      8 2000
9      9 2000
10    10 2000
11    11 2000
12    12 2000

full_seq

完全な連続値を生成する

Arguments

  • x
  • period
  • tol
> full_seq(c(1, 2, 4, 5, 10), 1)
 [1]  1  2  3  4  5  6  7  8  9 10

gather

複数の変数に分かれている共通の変数を1つの変数内の観測値としてまとめる。key引数に指定した列には水準が入り、value列に値が入力される。

ref) spread()

> df <- data.frame(Species  = c("アオキ", "アオハダ"),
+                  CPI1.SSI = c(1.0000000, 1.0000000),
+                  CPI2.SSI = c(0.9916116, 0.8772300),
+                  CPI3.SSI = c(NA, 0.9831741),
+                  CPI4.SSI = c(NA, 0.8938364))
> df %>% kable(format = "markdown")
Species CPI1.SSI CPI2.SSI CPI3.SSI CPI4.SSI
アオキ 1 0.9916116 NA NA
アオハダ 1 0.8772300 0.9831741 0.8938364
> gather(data = df, key = CPI, value = SSI, select = -Species) %>% kable(format = "markdown")
Species CPI SSI
アオキ CPI1.SSI 1.0000000
アオハダ CPI1.SSI 1.0000000
アオキ CPI2.SSI 0.9916116
アオハダ CPI2.SSI 0.8772300
アオキ CPI3.SSI NA
アオハダ CPI3.SSI 0.9831741
アオキ CPI4.SSI NA
アオハダ CPI4.SSI 0.8938364
> # key... 新たに付ける変数名 # value = 変数に入れる観測値の変数名

nest

ref) unnest()

> chickwts %>% nest(weight)
# A tibble: 6 × 2
       feed               data
     <fctr>             <list>
1 horsebean <tibble [10 × 1]>
2   linseed <tibble [12 × 1]>
3   soybean <tibble [14 × 1]>
4 sunflower <tibble [12 × 1]>
5  meatmeal <tibble [11 × 1]>
6    casein <tibble [12 × 1]>

replace_na

欠損値を任意の値に置換する

> df <- dplyr::data_frame(x = c(1, 2, NA), y = c("a", NA, "b"))
> df %>% replace_na(list(x = 0, y = "unknown"))
# A tibble: 3 × 2
      x       y
  <dbl>   <chr>
1     1       a
2     2 unknown
3     0       b

separate

1つの列を複数列に分割する

Arguments

  • data... データフレーム
  • col... 分割対象にする列名
  • into... 分割後に生成される列名
  • sep... 列を分割する基準。文字列か数値により挙動が異なる。文字列では正規表現を扱える。
  • remove... 真偽値(既定値 TRUE)。基準となした列を残す(TRUE)か否か(FALSE)
  • convert... 真偽値
  • extra...
    • error
    • drop
    • merge
  • ...
> (df <- data.frame(x = c("a.b", "a.d", "b.c")))
    x
1 a.b
2 a.d
3 b.c
> separate(data = df, col = x, into = c("A", "B"), remove = TRUE)
  A B
1 a b
2 a d
3 b c
> (df <- data.frame(x = c("a", "a b", "a b c", NA)))
      x
1     a
2   a b
3 a b c
4  <NA>
> separate(df, x, c("a", "b"), extra = "merge")
Warning: Too few values at 1 locations: 1
     a    b
1    a <NA>
2    a    b
3    a  b c
4 <NA> <NA>
> separate(df, x, c("a", "b"), extra = "drop")
Warning: Too few values at 1 locations: 1
     a    b
1    a <NA>
2    a    b
3    a    b
4 <NA> <NA>
> (df <- data.frame(x = c("x: 123", "y: error: 7")))
            x
1      x: 123
2 y: error: 7
> separate(df, x, c("key", "value"), sep = ": ", extra = "merge")
  key    value
1   x      123
2   y error: 7

spread

縦長のデータを横長に

ref) gather()

> df <- data.frame(Species = c("アオキ", "アオキ", "アオハダ", "アオハダ", "アオハダ", "アオハダ"),
+                  CPI        = c(1, 2, 1, 2, 3, 4),
+                  SSI        = c(1.0000000, 0.9916116, 1.0000000, 0.8772300, 0.9831741, 0.8938364))
> df %>% kable(format = "markdown")
Species CPI SSI
アオキ 1 1.0000000
アオキ 2 0.9916116
アオハダ 1 1.0000000
アオハダ 2 0.8772300
アオハダ 3 0.9831741
アオハダ 4 0.8938364
> spread(data = df, key = CPI, value = SSI) %>% kable(format = "markdown")
Species 1 2 3 4
アオキ 1 0.9916116 NA NA
アオハダ 1 0.8772300 0.9831741 0.8938364

unite

複数列を1列に結合する

ref) extract()

Arguments

  • data
  • col... 結合したあとの(新規)列名
  • ...
  • sep... 列を結合した際の結びとなる文字
  • remove... 真偽値(既定値TRUE)。結合した列を残す場合はFALSE
> head(mtcars, 3)
               mpg cyl disp  hp drat    wt  qsec vs am gear carb
Mazda RX4     21.0   6  160 110 3.90 2.620 16.46  0  1    4    4
Mazda RX4 Wag 21.0   6  160 110 3.90 2.875 17.02  0  1    4    4
Datsun 710    22.8   4  108  93 3.85 2.320 18.61  1  1    4    1
> unite(data = mtcars, col = vs_am, vs, am, sep = "_") %>% head(., 3)
               mpg cyl disp  hp drat    wt  qsec vs_am gear carb
Mazda RX4     21.0   6  160 110 3.90 2.620 16.46   0_1    4    4
Mazda RX4 Wag 21.0   6  160 110 3.90 2.875 17.02   0_1    4    4
Datsun 710    22.8   4  108  93 3.85 2.320 18.61   1_1    4    1

unnest

> df <- dplyr::data_frame(
+  a = list(c("a", "b"), "c"),
+  b = list(1:2, 3),
+  c = c(11, 22)
+ )
> df %>% unnest(a, b)
# A tibble: 3 × 3
      c     a     b
  <dbl> <chr> <dbl>
1    11     a     1
2    11     b     2
3    22     c     3