我可以直接在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)
)
Run Code Online (Sandbox Code Playgroud)
Run Code Online (Sandbox Code Playgroud)# 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)
)
Run Code Online (Sandbox Code Playgroud)
Run Code Online (Sandbox Code Playgroud)# 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)
Run Code Online (Sandbox Code Playgroud)
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
Run Code Online (Sandbox Code Playgroud)
有了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
Run Code Online (Sandbox Code Playgroud)
使用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
Run Code Online (Sandbox Code Playgroud)
由reprex软件包(v0.3.0)创建于2019-09-14
输出在此处很冗长,因为水平未嵌套的元素(矢量元素)未命名,并且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
Run Code Online (Sandbox Code Playgroud)
或者只是使用suppressMessages()或purrr::quietly()