reshape2
を置き換えるべく再設計された改良版(C++での記述)dplyr
やpurrr
と一緒に使うことで真価を発揮する{tidyverse}
に含まれる# 登録数
funcCountFuncs(tidyr)
## [1] 41
# 関数内訳
funcCountFuncs(tidyr, FALSE, TRUE)
## [1] "%>%" "complete" "complete_"
## [4] "crossing" "crossing_" "drop_na"
## [7] "drop_na_" "expand" "expand_"
## [10] "extract" "extract_" "extract_numeric"
## [13] "fill" "fill_" "full_seq"
## [16] "gather" "gather_" "nest"
## [19] "nest_" "nesting" "nesting_"
## [22] "population" "replace_na" "separate"
## [25] "separate_" "separate_rows" "separate_rows_"
## [28] "smiths" "spread" "spread_"
## [31] "table1" "table2" "table3"
## [34] "table4a" "table4b" "table5"
## [37] "unite" "unite_" "unnest"
## [40] "unnest_" "who"
縦持ちデータへの変換
とは、基準列と他の列のフィールド名でDB化することをいう
reshape2
のmelt関数
に相当する操作基準列
には文字列のフィールドを選択するkey引数
を指定すると、他の列のフィールド名が入る列の列名を定義できるvalue引数
を指定すると、他の列の値が入る列の列名を定義できるkey引数
とvalue引数
の別名の定義は必須ではないが、入力の省略はできない...
にはまとめる引数
を指定する(-Species
)# 元データのフィールド数
iris %>% {
head(.) %>% print()
dim(.) %>% print()
}
## Sepal.Length Sepal.Width Petal.Length Petal.Width Species
## 1 5.1 3.5 1.4 0.2 setosa
## 2 4.9 3.0 1.4 0.2 setosa
## 3 4.7 3.2 1.3 0.2 setosa
## 4 4.6 3.1 1.5 0.2 setosa
## 5 5.0 3.6 1.4 0.2 setosa
## 6 5.4 3.9 1.7 0.4 setosa
## [1] 150 5
# 縦持ちに変換 (列名変更なし)
iris %>%
gather(key, value, -Species) %>% {
head(.) %>% print()
dim(.) %>% print()
}
## Species key value
## 1 setosa Sepal.Length 5.1
## 2 setosa Sepal.Length 4.9
## 3 setosa Sepal.Length 4.7
## 4 setosa Sepal.Length 4.6
## 5 setosa Sepal.Length 5.0
## 6 setosa Sepal.Length 5.4
## [1] 600 3
# 縦持ちに変換 (列名変更あり)
iris %>%
gather(key = KEY, value = VALUE, -Species) %>% {
head(.) %>% print()
dim(.) %>% print()
}
## Species KEY VALUE
## 1 setosa Sepal.Length 5.1
## 2 setosa Sepal.Length 4.9
## 3 setosa Sepal.Length 4.7
## 4 setosa Sepal.Length 4.6
## 5 setosa Sepal.Length 5.0
## 6 setosa Sepal.Length 5.4
## [1] 600 3
reshape2
のdcast関数
に相当するこの関数を使うときにはIDとなるような変数が必要
で、ここではid
列を作っているkey引数
とvalue引数
のみ# 準備:irisを縦持ちデータに変換
iris.l <- iris %>%
mutate(id = rownames(.)) %>%
gather(key, value , contains("l.")) %T>% {
head(.) %>% print()
}
## Species id key value
## 1 setosa 1 Sepal.Length 5.1
## 2 setosa 2 Sepal.Length 4.9
## 3 setosa 3 Sepal.Length 4.7
## 4 setosa 4 Sepal.Length 4.6
## 5 setosa 5 Sepal.Length 5.0
## 6 setosa 6 Sepal.Length 5.4
# 横持データに変換
iris.l %>% spread(key, value) %>% head()
## Species id Petal.Length Petal.Width Sepal.Length Sepal.Width
## 1 setosa 1 1.4 0.2 5.1 3.5
## 2 setosa 10 1.5 0.1 4.9 3.1
## 3 setosa 11 1.5 0.2 5.4 3.7
## 4 setosa 12 1.6 0.2 4.8 3.4
## 5 setosa 13 1.4 0.1 4.8 3.0
## 6 setosa 14 1.1 0.1 4.3 3.0
# グループごとの平均値を算出
iris.mean <-
iris.l %>%
group_by(Species, key) %>%
summarise(mean = mean(value)) %T>% {
head(.) %>% print()
}
## Source: local data frame [6 x 3]
## Groups: Species [2]
##
## Species key mean
## <fctr> <chr> <dbl>
## 1 setosa Petal.Length 1.462
## 2 setosa Petal.Width 0.246
## 3 setosa Sepal.Length 5.006
## 4 setosa Sepal.Width 3.428
## 5 versicolor Petal.Length 4.260
## 6 versicolor Petal.Width 1.326
{xts}
などにも類似処理があるが、fill関数
はデータフレームに対してNA補完を行う# データセットの作成
df <- data.frame(Month = 1:5,
Year = c(2000, rep(NA, 4))) %T>% print()
## Month Year
## 1 1 2000
## 2 2 NA
## 3 3 NA
## 4 4 NA
## 5 5 NA
# 下方向にデータを補完
df %>% fill(Year)
## Month Year
## 1 1 2000
## 2 2 2000
## 3 3 2000
## 4 4 2000
## 5 5 2000
# 上方向にデータを補完
df %>% fill(Year, .direction = "up")
## Month Year
## 1 1 2000
## 2 2 NA
## 3 3 NA
## 4 4 NA
## 5 5 NA
# 準備:データセットの作成
df <- data_frame(x = c(1, 2, NA),
y = c("a", NA, "b")) %T>% print()
## # A tibble: 3 × 2
## x y
## <dbl> <chr>
## 1 1 a
## 2 2 <NA>
## 3 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
# 数値のみ補完方法を指定
df %>% replace_na(list(x = 0))
## # A tibble: 3 × 2
## x y
## <dbl> <chr>
## 1 1 a
## 2 2 <NA>
## 3 0 b
na.omit関数
やdata[complete.case(data),]
と大差ない# 準備:データセットのサック製
df <- data.frame(x = c(1, 2, NA),
y = c("a", NA, "b")) %>% print()
## x y
## 1 1 a
## 2 2 <NA>
## 3 NA b
# 全フィールドでNAを含まないレコードを抽出
df %>% drop_na()
## x y
## 1 1 a
# 指定フィールドでNAを含まないレコードを抽出
df %>% drop_na(x)
## x y
## 1 1 a
## 2 2 <NA>
df %>% drop_na(y)
## x y
## 1 1 a
## 3 NA b
unite()
は、複数列の情報を1列にまとめたい場合に使用する
col引数
は統合フィールドのフィールド名...
は統合するフィールド (start_with()
などを使うと便利)sep
は結合時のセパレータseparete()
は、unite()
と逆の操作# 複数列の情報を1列にまとめて新しい列を定義
iris_x <- iris %>%
unite(col = "Sepal.", starts_with("Sepal"), sep = "-") %>%
unite(col = "Petal.", starts_with("Petal"), sep = "-") %>%
head() %T>% print()
## Sepal. Petal. Species
## 1 5.1-3.5 1.4-0.2 setosa
## 2 4.9-3 1.4-0.2 setosa
## 3 4.7-3.2 1.3-0.2 setosa
## 4 4.6-3.1 1.5-0.2 setosa
## 5 5-3.6 1.4-0.2 setosa
## 6 5.4-3.9 1.7-0.4 setosa
# 複数の情報が集約された列を分解
iris_x %>%
separate(col = "Sepal.", into = c("Sepal.Length","Sepal.Width"), sep = "-") %>%
separate(col = "Petal.", into = c("Petal.Length","Petal.Width"), sep = "-")
## Sepal.Length Sepal.Width Petal.Length Petal.Width Species
## 1 5.1 3.5 1.4 0.2 setosa
## 2 4.9 3 1.4 0.2 setosa
## 3 4.7 3.2 1.3 0.2 setosa
## 4 4.6 3.1 1.5 0.2 setosa
## 5 5 3.6 1.4 0.2 setosa
## 6 5.4 3.9 1.7 0.4 setosa
正規表現
で前後を区別して列を分解するdf <- data.frame(x = c(NA, "a-b", "a-d", "b-c", "d-e"))
df %>% extract(x, "A")
## A
## 1 <NA>
## 2 a
## 3 a
## 4 b
## 5 d
df %>% extract(x, c("A", "B"), "([[:alnum:]]+)-([[:alnum:]]+)")
## A B
## 1 <NA> <NA>
## 2 a b
## 3 a d
## 4 b c
## 5 d e
expand関数
は指定したフィールドのみ取得complete関数
は他のレコードも併せて取得# 準備:データセットの作成
df <- data.frame(groupid = c("A", "A", "A", "B", "B", "B", "A"),
itemid = c(1:6, 6),
value = c(3, 2, 1, 2, 3, 1, 22)) %T>% print()
## groupid itemid value
## 1 A 1 3
## 2 A 2 2
## 3 A 3 1
## 4 B 4 2
## 5 B 5 3
## 6 B 6 1
## 7 A 6 22
# 指定したフィールドのみ出力
df %>% expand(groupid, itemid)
## # A tibble: 12 × 2
## groupid itemid
## <fctr> <dbl>
## 1 A 1
## 2 A 2
## 3 A 3
## 4 A 4
## 5 A 5
## 6 A 6
## 7 B 1
## 8 B 2
## 9 B 3
## 10 B 4
## 11 B 5
## 12 B 6
# 全フィールドを出力
df %>% complete(groupid, itemid)
## # A tibble: 12 × 3
## groupid itemid value
## <fctr> <dbl> <dbl>
## 1 A 1 3
## 2 A 2 2
## 3 A 3 1
## 4 A 4 NA
## 5 A 5 NA
## 6 A 6 22
## 7 B 1 NA
## 8 B 2 NA
## 9 B 3 NA
## 10 B 4 2
## 11 B 5 3
## 12 B 6 1
expand関数
は単純に各引数の組み合わせを取得complete関数
はexpand.grid()と同じく直積集合を取得 -引数はベクトル ( expand()
はデータフレームを引数とした)# 指定パターンのみ作成
nesting(x = 1:3, y = 3:1)
## # A tibble: 3 × 2
## x y
## <int> <int>
## 1 1 3
## 2 2 2
## 3 3 1
# 全パターンを作成
crossing(x = 1:3, y = 3:1)
## # A tibble: 9 × 2
## x y
## <int> <int>
## 1 1 1
## 2 1 2
## 3 1 3
## 4 2 1
## 5 2 2
## 6 2 3
## 7 3 1
## 8 3 2
## 9 3 3
# 準備:データフレーム作成
df <- data.frame(x = 1:3, y = 3:1, z = c(1, 2, 1)) %T>% print()
## x y z
## 1 1 3 1
## 2 2 2 2
## 3 3 1 1
# 全パターンの作成
df %>% expand(x, y, z)
## # A tibble: 18 × 3
## x y z
## <int> <int> <dbl>
## 1 1 1 1
## 2 1 1 2
## 3 1 2 1
## 4 1 2 2
## 5 1 3 1
## 6 1 3 2
## 7 2 1 1
## 8 2 1 2
## 9 2 2 1
## 10 2 2 2
## 11 2 3 1
## 12 2 3 2
## 13 3 1 1
## 14 3 1 2
## 15 3 2 1
## 16 3 2 2
## 17 3 3 1
## 18 3 3 2
# 特定の組合せを固定してパターン作成
df %>% expand(nesting(x, y), z)
## # A tibble: 6 × 3
## x y z
## <int> <int> <dbl>
## 1 1 3 1
## 2 1 3 2
## 3 2 2 1
## 4 2 2 2
## 5 3 1 1
## 6 3 1 2
...
で指定マイナス(-)
を付けて指定# いきなりネスト化
ndf <- iris %>% nest(-Species) %T>% print()
## # A tibble: 3 × 2
## Species data
## <fctr> <list>
## 1 setosa <tibble [50 × 4]>
## 2 versicolor <tibble [50 × 4]>
## 3 virginica <tibble [50 × 4]>
# グループ化してからネスト化
iris %>% group_by(Species) %>% nest()
## # A tibble: 3 × 2
## Species data
## <fctr> <list>
## 1 setosa <tibble [50 × 4]>
## 2 versicolor <tibble [50 × 4]>
## 3 virginica <tibble [50 × 4]>
# ネスト化の解除
ndf %>% unnest()
## # A tibble: 150 × 5
## Species Sepal.Length Sepal.Width Petal.Length Petal.Width
## <fctr> <dbl> <dbl> <dbl> <dbl>
## 1 setosa 5.1 3.5 1.4 0.2
## 2 setosa 4.9 3.0 1.4 0.2
## 3 setosa 4.7 3.2 1.3 0.2
## 4 setosa 4.6 3.1 1.5 0.2
## 5 setosa 5.0 3.6 1.4 0.2
## 6 setosa 5.4 3.9 1.7 0.4
## 7 setosa 4.6 3.4 1.4 0.3
## 8 setosa 5.0 3.4 1.5 0.2
## 9 setosa 4.4 2.9 1.4 0.2
## 10 setosa 4.9 3.1 1.5 0.1
## # ... with 140 more rows
最大値
と最小値
の間で数列を作成する# 準備:ベクトル作成
vec <- c(1, 2, 4, 5, 10)
# 連続数値のベクトルの作成
vec %>% full_seq(1)
## [1] 1 2 3 4 5 6 7 8 9 10
# こちらも同様
vec %>% {seq(min(.), max(.), 1)}
## [1] 1 2 3 4 5 6 7 8 9 10