UPDATE: 2022-10-23 11:42:28
クロス集計の頻度からデータフレームを復元するメモ書き。データフレームからクロス集計をするから、復元するも何も、何だそれと思うかもしれないが、クロス集計された状態のデータがスタートで、そこからもとのデータフレームを得たい場合がある。集計されたものをIDレベルで他の列の情報も復元するというのは、不可能だけど、単純に戻すだけならなんとかなる。
ここではMASSパッケージのcaith
データを利用する。このデータは4行5列のクロス集計されたデータで、スコットランドのケイスネスに住む人々の目と髪の色のデータ。
library(MASS)
library(tidyverse)
caith
## fair red medium dark black
## blue 326 38 241 110 3
## light 688 116 584 188 4
## medium 343 84 909 412 26
## dark 98 48 403 681 85
クロス集計の表側、表頭の値の組み合わせを持つデータフレームを作成し、クロス集計の値分、slice()
で行を増幅させる。ここでは、freq
とかnum
とかを付け加えているが、そこはどうでもいいので、そのままにしておく。
<- colnames(caith)
eye <- rownames(caith)
hair <- tibble(expand_grid(eye, hair), freq = unlist(caith))
df
%>%
df slice(rep(1:n(), times = freq)) %>%
mutate(num = 1)
## # A tibble: 5,387 × 4
## eye hair freq num
## <chr> <chr> <int> <dbl>
## 1 fair blue 326 1
## 2 fair blue 326 1
## 3 fair blue 326 1
## 4 fair blue 326 1
## 5 fair blue 326 1
## 6 fair blue 326 1
## 7 fair blue 326 1
## 8 fair blue 326 1
## 9 fair blue 326 1
## 10 fair blue 326 1
## # … with 5,377 more rows
## # ℹ Use `print(n = ...)` to see more rows
データフレームの中にリストで必要な行数分データを用意し、それを展開する方法。map()
でなくてもlappy()
でも同じことはできる。
<- colnames(caith)
eye <- rownames(caith)
hair <- tibble(expand_grid(eye, hair), freq = unlist(caith))
df %>%
df # lapply(df$freq, function(x){(rep(1, x))})
mutate(num = map(.x = freq, .f = function(x){(rep(1, x))})) %>%
unnest(num, .drop = FALSE)
## # A tibble: 5,387 × 4
## eye hair freq num
## <chr> <chr> <int> <dbl>
## 1 fair blue 326 1
## 2 fair blue 326 1
## 3 fair blue 326 1
## 4 fair blue 326 1
## 5 fair blue 326 1
## 6 fair blue 326 1
## 7 fair blue 326 1
## 8 fair blue 326 1
## 9 fair blue 326 1
## 10 fair blue 326 1
## # … with 5,377 more rows
## # ℹ Use `print(n = ...)` to see more rows
map()
の部分で実行すると、こんな感じになっている。
%>%
df mutate(num = map(.x = freq, .f = function(x){(rep(1, x))}))
## # A tibble: 20 × 4
## eye hair freq num
## <chr> <chr> <int> <named list>
## 1 fair blue 326 <dbl [326]>
## 2 fair light 688 <dbl [688]>
## 3 fair medium 343 <dbl [343]>
## 4 fair dark 98 <dbl [98]>
## 5 red blue 38 <dbl [38]>
## 6 red light 116 <dbl [116]>
## 7 red medium 84 <dbl [84]>
## 8 red dark 48 <dbl [48]>
## 9 medium blue 241 <dbl [241]>
## 10 medium light 584 <dbl [584]>
## 11 medium medium 909 <dbl [909]>
## 12 medium dark 403 <dbl [403]>
## 13 dark blue 110 <dbl [110]>
## 14 dark light 188 <dbl [188]>
## 15 dark medium 412 <dbl [412]>
## 16 dark dark 681 <dbl [681]>
## 17 black blue 3 <dbl [3]>
## 18 black light 4 <dbl [4]>
## 19 black medium 26 <dbl [26]>
## 20 black dark 85 <dbl [85]>
最近はよく感じるのが、便利なパッケージがこの世からなくなったら、分析できなくなるなぁ〜、ということ。なので、プログラムの3つの制御構造である「順次」「繰り返し」「分岐」をもっとうまく使えるようにならないといけないので、for-loopでも書いておく。というよりも、便利なパッケージがこの世からなくならないけど、自分がやりたいことをやるためには、制御構造がもっと使えるようになる必要ある・・・。
<- colnames(caith)
n_col <- rownames(caith)
n_row <- NULL
data for (i in seq_along(n_row)) {
for (j in seq_along(n_col)) {
for (k in 1:caith[i, j]){
<- rbind(data, c(n_row[[i]], n_col[[j]]))
data
}
}
}as.data.frame(data) %>% dim()
## [1] 5387 2