リストの列をn列に直接ネスト解除できますか?
リストは、すべての要素が同じ長さで、規則的であると想定できます。
リスト列の代わりに文字ベクトルを使用する場合、tidyr::separate
を使用できます。 tidyr::unnest
はできますが、tidyr::spread
を実行するには別のヘルパー変数が必要です。明白な方法が欠けていますか?
データの例:
library(tibble)
df1 <- data_frame(
gr = c('a', 'b', 'c'),
values = list(1:2, 3:4, 5:6)
)
# A tibble: 3 x 2 gr values <chr> <list> 1 a <int [2]> 2 b <int [2]> 3 c <int [2]>
ゴール:
df2 <- data_frame(
gr = c('a', 'b', 'c'),
V1 = c(1, 3, 5),
V2 = c(2, 4, 6)
)
# A tibble: 3 x 3 gr V1 V2 <chr> <dbl> <dbl> 1 a 1. 2. 2 b 3. 4. 3 c 5. 6.
現在の方法:
unnest(df1) %>%
group_by(gr) %>%
mutate(r = paste0('V', row_number())) %>%
spread(r, values)
tidyr 1.0.0で必要なのは次のとおりです。
_library(tidyr)
df1 <- tibble(
gr = c('a', 'b', 'c'),
values = list(1:2, 3:4, 5:6)
)
unnest_wider(df1, values)
#> New names:
#> * `` -> ...1
#> * `` -> ...2
#> New names:
#> * `` -> ...1
#> * `` -> ...2
#> New names:
#> * `` -> ...1
#> * `` -> ...2
#> # A tibble: 3 x 3
#> gr ...1 ...2
#> <chr> <int> <int>
#> 1 a 1 2
#> 2 b 3 4
#> 3 c 5 6
_
2019-09-14に reprexパッケージ (v0.3.0)によって作成されました
水平方向にネストされていない要素(ベクトル要素)には名前が付けられておらず、_unnest_wider
_は暗黙のうちに推測したくないため、出力はここでは冗長です。
それを避けるために、事前に名前を付けることができます。
_df1 %>%
dplyr::mutate(values = purrr::map(values, setNames, c("V1","V2"))) %>%
unnest_wider(values)
#> # A tibble: 3 x 3
#> gr V1 V2
#> <chr> <int> <int>
#> 1 a 1 2
#> 2 b 3 4
#> 3 c 5 6
_
または、単にsuppressMessages()
またはpurrr::quietly()
を使用します
library(tibble)
df1 <- data_frame(
gr = c('a', 'b', 'c'),
values = list(1:2, 3:4, 5:6)
)
library(tidyverse)
df1 %>%
mutate(r = map(values, ~ data.frame(t(.)))) %>%
unnest(r) %>%
select(-values)
# # A tibble: 3 x 3
# gr X1 X2
# <chr> <int> <int>
# 1 a 1 2
# 2 b 3 4
# 3 c 5 6
data.table
とてもシンプルです:
library("data.table")
setDT(df1)
df1[, c("V1", "V2") := transpose(values)]
df1
# gr values V1 V2
# 1: a 1,2 1 2
# 2: b 3,4 3 4
# 3: c 5,6 5 6
多分これ:
cbind(df1[, "gr"], do.call(rbind, df1$values))
別のもの:
_library(tibble)
library(dplyr)
df1 <- data_frame(
gr = c('a', 'b', 'c'),
values = list(1:2, 3:4, 5:6)
)
df %>% mutate(V1 = sapply(values, "[[", 1), V2 = sapply(values, "[[", 2))
# A tibble: 3 x 4
gr values V1 V2
<chr> <list> <int> <int>
1 a <int [2]> 1 2
2 b <int [2]> 3 4
3 c <int [2]> 5 6
_
編集:
リストされたベクトルが非常に長く、手書きでV1 = sapply(values, "[[", index)
を使用することが不都合な場合は、lazyeval
の_f_interp
_と組み合わせることができます。
_library(tibble)
library(dplyr)
library(lazyeval)
df <- data_frame(gr = c('a', 'b', 'c'), values = list(1:11, 3:13, 5:15))
nums <- c(1:11)
ll <- lapply(nums, function(nr) f_interp(~sapply(values, "[[", uq(nr))))
mutate_(df, .dots=setNames(ll, paste("V", nums, sep="")))
# A tibble: 3 x 12
gr values V1 V2 V3 V4 V5 V6 V7 V8 V9 V10
<chr> <list> <int> <int> <int> <int> <int> <int> <int> <int> <int> <int>
1 a <int [11]> 1 2 3 4 5 6 7 8 9 10
2 b <int [11]> 3 4 5 6 7 8 9 10 11 12
3 c <int [11]> 5 6 7 8 9 10 11 12 13 14
_
同様の問題が何度かありました。私の解決策は他の回答と比較して明らかに不格好ですが、完全を期すためにそれを報告しています。
library(tibble)
df1 <- data_frame(
gr = c('a', 'b', 'c'),
values = list(1:2, 3:4, 5:6)
)
matrix(unlist(df1[1])) -> grs
matrix(unlist(df1[2]), byrow=T, ncol=2) -> vals
結果:
> data.frame(grs, vals)
grs X1 X2
1 a 1 2
2 b 3 4
3 c 5 6