tidyr::expand()
返回多列中所有可能的值组合。我正在寻找一种略有不同的行为,其中所有值都在一个列中,并且组合将跨组进行。
例如,让数据定义如下:
library( tidyverse )
X <- bind_rows( data_frame(Group = "Group1", Value = LETTERS[1:3]),
data_frame(Group = "Group2", Value = letters[4:5]) )
我们希望Group1
的值的所有组合与Group2
的值。我目前笨重的解决方案是将值分隔多列
Y <- X %>% group_by(Group) %>% do(vals = .$Value) %>% spread(Group, vals)
# # A tibble: 1 x 2
# Group1 Group2
# <list> <list>
# 1 <chr [3]> <chr [2]>
后跟双unnest
操作
Y %>% unnest( .preserve = Group2 ) %>% unnest
# # A tibble: 6 x 2
# Group1 Group2
# <chr> <chr>
# 1 A d
# 2 A e
# 3 B d
# 4 B e
# 5 C d
# 6 C e
这是所需的输出,但是你可以想象,这个解决方案并没有很好地概括:随着组数的增加,我们必须执行的unnest
操作的数量也增加。 / p>
有更优雅的解决方案吗?
答案 0 :(得分:4)
因为OP似乎很乐意使用base
,所以我将评论升级为答案:
expand.grid(split(X$Value, X$Group))
# Group1 Group2
# 1 A d
# 2 B d
# 3 C d
# 4 A e
# 5 B e
# 6 C e
如OP所述,expand.grid
将字符向量转换为因子。为防止这种情况,请使用stringsAsFactors = FALSE
。
tidyverse
等效为purrr::cross_df
,不会强制要素:
cross_df(split(X$Value, X$Group))
# A tibble: 6 x 2
# Group1 Group2
# <chr> <chr>
# 1 A d
# 2 B d
# 3 C d
# 4 A e
# 5 B e
# 6 C e
答案 1 :(得分:3)
这是一个选项。虽然不推荐使用complete_
,但它适用于包含两个以上组的案例。
library( tidyverse )
X2 <- X %>%
group_by(Group) %>%
mutate(ID = 1:n()) %>%
spread(Group, Value) %>%
select(-ID) %>%
complete_(names(.)) %>%
na.omit()
X2
# # A tibble: 6 x 2
# Group1 Group2
# <chr> <chr>
# 1 A d
# 2 A e
# 3 B d
# 4 B e
# 5 C d
# 6 C e
<强>更新强>
!!!syms(names(.))
适用于常规complete
函数,因此比使用complete_
作为我的原始解决方案更好。
library( tidyverse )
X2 <- X %>%
group_by(Group) %>%
mutate(ID = 1:n()) %>%
spread(Group, Value) %>%
select(-ID) %>%
complete(!!!syms(names(.))) %>%
na.omit()
X2
# # A tibble: 6 x 2
# Group1 Group2
# <chr> <chr>
# 1 A d
# 2 A e
# 3 B d
# 4 B e
# 5 C d
# 6 C e
答案 2 :(得分:1)
我经常使用tidyr::crossing()
加入group2
到group
的所有值。
data_frame(group = c(LETTERS[1:3])) %>%
crossing(group2 = letters[4:5])
我可能会这样做:
data %>%
distinct(group) %>%
crossing(group2)
更具体的例子:
dates <- lubridate::make_date(2000:2018)
data_frame(group = letters[1:5]) %>%
crossing(dates)
答案 3 :(得分:1)
这仍然适用于expand
后的spread
。
X %>%
mutate(id = row_number()) %>%
spread(Group, Value) %>%
expand(Group1, Group2) %>%
na.omit()