こちらでRで各行を要素としたリストを作成する方法が自分で関数を定義して紹介されているが、今なら{purrr}
のpmap()
を使うと簡単にできそう。
今回は例としてiris
データを使うが、全部を使うと見にくいので冒頭5行だけ使用するために、iris.head
としてオブジェクトを持っておく。
iris.head <- head(iris, n = 5)
ここで、{purrr}
のpmap()
でデータフレームでlist
化してやる。
library(purrr) iris.list <- pmap(iris.head, list) iris.list
## [[1]]
## [[1]]$Sepal.Length
## [1] 5.1
##
## [[1]]$Sepal.Width
## [1] 3.5
##
## [[1]]$Petal.Length
## [1] 1.4
##
## [[1]]$Petal.Width
## [1] 0.2
##
## [[1]]$Species
## [1] setosa
## Levels: setosa versicolor virginica
##
##
## [[2]]
## [[2]]$Sepal.Length
## [1] 4.9
##
## [[2]]$Sepal.Width
## [1] 3
##
## [[2]]$Petal.Length
## [1] 1.4
##
## [[2]]$Petal.Width
## [1] 0.2
##
## [[2]]$Species
## [1] setosa
## Levels: setosa versicolor virginica
##
##
## [[3]]
## [[3]]$Sepal.Length
## [1] 4.7
##
## [[3]]$Sepal.Width
## [1] 3.2
##
## [[3]]$Petal.Length
## [1] 1.3
##
## [[3]]$Petal.Width
## [1] 0.2
##
## [[3]]$Species
## [1] setosa
## Levels: setosa versicolor virginica
##
##
## [[4]]
## [[4]]$Sepal.Length
## [1] 4.6
##
## [[4]]$Sepal.Width
## [1] 3.1
##
## [[4]]$Petal.Length
## [1] 1.5
##
## [[4]]$Petal.Width
## [1] 0.2
##
## [[4]]$Species
## [1] setosa
## Levels: setosa versicolor virginica
##
##
## [[5]]
## [[5]]$Sepal.Length
## [1] 5
##
## [[5]]$Sepal.Width
## [1] 3.6
##
## [[5]]$Petal.Length
## [1] 1.4
##
## [[5]]$Petal.Width
## [1] 0.2
##
## [[5]]$Species
## [1] setosa
## Levels: setosa versicolor virginica
簡単に各行を要素としたリストができる。
これをデータフレームに戻すには、要素にキーとなる名前がついているので、{dplyr}
のbind_row()
を使うと簡単にできる。
library(dplyr)
##
## 次のパッケージを付け加えます: 'dplyr'
## 以下のオブジェクトは 'package:stats' からマスクされています:
##
## filter, lag
## 以下のオブジェクトは 'package:base' からマスクされています:
##
## intersect, setdiff, setequal, union
iris.dataframe <- bind_rows(iris.head) iris.dataframe
## 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
また、このbind_row()
は要素の名前をキーにしてちゃんとデータフレームにしてくれるので、リストごとに一部欠損値があっても(長さが異なっていても)、そこの値はNA
で処理してくれる。
# 適当なリストを作ってみる a <- list( A = list("ID" = 1234, "SEX" = "F", "AGE" = 45), B = list("ID" = 4567, "AGE" = 65), C = list("SEX" = "M", "AGE" = 35) ) a
## $A
## $A$ID
## [1] 1234
##
## $A$SEX
## [1] "F"
##
## $A$AGE
## [1] 45
##
##
## $B
## $B$ID
## [1] 4567
##
## $B$AGE
## [1] 65
##
##
## $C
## $C$SEX
## [1] "M"
##
## $C$AGE
## [1] 35
# aをデータフレーム化(この場合tibbleになる)する a.tibble <- bind_rows(a) a.tibble
## # A tibble: 3 x 3
## ID SEX AGE
## <dbl> <chr> <dbl>
## 1 1234 F 45
## 2 4567 <NA> 65
## 3 NA M 35
このとき、そのままだとリストの名前が落ちてしまうので、必要ならばこれを取り出して、列名つけたり新たな列を作って処理すると良いと思う。
# リストの名前を取り出して行名にする # a.tibbleを行名をつけられるdata.frameにしておく a.dataframe <- as.data.frame(a.tibble) rownames(a.dataframe) <- names(a) a.dataframe
## ID SEX AGE
## A 1234 F 45
## B 4567 <NA> 65
## C NA M 35
# リストの名前を取り出して新たなNAME列を作る # ついでにNAME列を先頭もってくる a.tibble <- a.tibble %>% mutate(NAME = names(a)) %>% select(NAME, everything()) a.tibble
## # A tibble: 3 x 4
## NAME ID SEX AGE
## <chr> <dbl> <chr> <dbl>
## 1 A 1234 F 45
## 2 B 4567 <NA> 65
## 3 C NA M 35