这是我的载体:
vec <- c("A", "B", "C")
而且,我想获得vec的所有7种组合。
desired_output <- tibble( ~A, ~B, ~C,
1, 0, 0,
0, 1, 0,
0, 0, 1,
1, 1, 0,
1, 0, 1,
0, 1, 1,
1, 1, 1)
我尝试了以下操作:
#install.packages("gtools")
library(gtools)
r <- c(1,2, 3)
df1 <- purrr::map(r, ~combinations(3,.x,vec))
df2 <- per %>% map_dfr(~data.frame(.x))
但无法获得所需的结果。您能否提出解决方案,尤其是在vec中使用不同数量的元素?
答案 0 :(得分:8)
基本解决方案:
vec = c("A", "B", "C")
inp = rep(list(0:1), length(vec))
names(inp) = vec
do.call(expand.grid, inp)
# A B C
# 1 0 0 0
# 2 1 0 0
# 3 0 1 0
# 4 1 1 0
# 5 0 0 1
# 6 1 0 1
# 7 0 1 1
# 8 1 1 1
如果您想排除全0的情况,建议您事后进行。这会给出所有 8 组合。
感谢Henrik发表评论,这是一个purrr
版本:
vec = c("A", "B", "C")
library(purrr)
pur = rerun(length(vec), 0:1)
names(pur) = vec
cross_df(pur)
# # A tibble: 8 x 3
# A B C
# <int> <int> <int>
# 1 0 0 0
# 2 1 0 0
# 3 0 1 0
# 4 1 1 0
# 5 0 0 1
# 6 1 0 1
# 7 0 1 1
# 8 1 1 1
对时间好奇吗?在这个小例子中,base
解决方案的速度提高了约6倍,尽管两者都足够快,没关系。在更长的输入中,这个比例似乎保持不变,vec = LETTERS[1:10]
使我的速度提高了约6倍。与LETTERS[1:20]
一起尝试过,但由于厌倦了等待,所以我放弃了。
vec = LETTERS[1:10]
microbenchmark(
base = {
inp = rep(list(0:1), length(vec));
names(inp) = vec;
do.call(expand.grid, inp);},
purrr = {
pur = rerun(length(vec), 0:1);
names(pur) = vec;
cross_df(pur);
},
times = 10L
)
# Unit: microseconds
# expr min lq mean median uq max neval
# base 789.668 868.152 1023.248 967.4635 1096.962 1388.559 10
# purrr 45617.167 45960.080 59621.746 54181.5545 78944.986 87511.789 10
答案 1 :(得分:0)
base R解决方案更好,但这是用于生成笛卡尔的sqldf解决方案
x_vec <- data.frame( mycol = c("A", "B", "C"), stringsAsFactors = F)
sqldf::sqldf("Select a.mycol mycol1, b.mycol mycol2, c.mycol mycol3 From x_vec a, x_vec b, x_vec c") %>%
mutate(myid = 1:n()) %>%
reshape2::melt(id.vars = "myid") %>%
mutate(variable = 1) %>% unique() %>%
reshape2::dcast(myid~value, fill = 0, value.var = "variable") %>%
select(-myid) %>% unique()