查找两个不同长度的向量之间的所有组合

Posted

技术标签:

【中文标题】查找两个不同长度的向量之间的所有组合【英文标题】:Find all combinations between two vectors of different length 【发布时间】:2019-11-11 00:40:21 【问题描述】:

假设我有两个不同长度的向量x_1y_1,如下所示:

x_1 = seq(0,49,2)
y_1 = seq(-90,-51,2)

现在我想找到这两个向量的所有可能组合,大小 = 5,因此我这样做了:

library(tidyr)
x_all = data.frame(t(rbind(combn(x_1, 5))))
y_all = data.frame(t(rbind(combn(y_1, 5))))

现在我只想保留以 2 为步长的值的组合:

x_all = x_all[x_all$X2 - x_all$X1 == 2 &
                x_all$X3 - x_all$X2 == 2 &
                x_all$X4 - x_all$X3 == 2 &
                x_all$X5 - x_all$X4 == 2, ]

y_all = y_all[y_all$X2 - y_all$X1 == 2 &
                y_all$X3 - y_all$X2 == 2 &
                y_all$X4 - y_all$X3 == 2 &
                y_all$X5 - y_all$X4 == 2, ]

现在我的问题是:

如何合并x_ally_all,以便得到一个独特的data.frame,其中包含这两组之间所有可能的组合?

有什么建议吗?

这是我尝试但没有成功的:

# Assign an index to each set
x_all$index = c(1:nrow(x_all))
y_all$index = c(1:nrow(y_all))

# Merge the sets
x_y_all = merge(x_all, y_all, by = 'index', all = TRUE)

输出应该是这样的:

X1.x X2.x X3.x X4.x X5.x X1.y X2.y X3.y X4.y X5.y 
 0    2    4    6    8   -90  -88  -86  -84  -82
 0    2    4    6    8   -88  -86  -84  -82  -80
 0    2    4    6    8   -86  -84  -82  -80  -78
....
 2    4    6    8   10   -90  -88  -86  -84  -82
 2    4    6    8   10   -88  -86  -84  -82  -80
 2    4    6    8   10   -86  -84  -82  -80  -78
....

【问题讨论】:

【参考方案1】:

对您的建议稍作改动即可解决问题:

#Assign same, constant index so the merge function will fill
x_all$index <- 1
y_all$index <- 1

#Merge to get all information
x_y_all <- merge(x_all, y_all, by = "index")

#Delete the index
x_y_all$index <- NULL

【讨论】:

【参考方案2】:

这是获得所需结果的一种更简单的方法(也比您的 combn 方法更容易记忆) -

library(dplyr)

x_1 = seq(0, 49, 2)
y_1 = seq(-90, -51, 2)

x_all <- sapply(x_1, function(x) 
  seq(x, by = 2, length.out = 5)
) %>% 
  t() %>% 
  as_tibble() %>% 
  mutate(cj = 1)

y_all <- sapply(y_1, function(x) 
  seq(x, by = 2, length.out = 5)
) %>% 
  t() %>% 
  as_tibble() %>% 
  mutate(cj = 1)

inner_join(x_all, y_all, by = "cj") %>% 
  select(-cj)

# A tibble: 500 x 10
    V1.x  V2.x  V3.x  V4.x  V5.x  V1.y  V2.y  V3.y  V4.y  V5.y
   <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl>
 1     0     2     4     6     8   -90   -88   -86   -84   -82
 2     0     2     4     6     8   -88   -86   -84   -82   -80
 3     0     2     4     6     8   -86   -84   -82   -80   -78
 4     0     2     4     6     8   -84   -82   -80   -78   -76
 5     0     2     4     6     8   -82   -80   -78   -76   -74
 6     0     2     4     6     8   -80   -78   -76   -74   -72
 7     0     2     4     6     8   -78   -76   -74   -72   -70
 8     0     2     4     6     8   -76   -74   -72   -70   -68
 9     0     2     4     6     8   -74   -72   -70   -68   -66
10     0     2     4     6     8   -72   -70   -68   -66   -64
# ... with 490 more rows

【讨论】:

【参考方案3】:

另一种可能的基本 R 方法是使用索引创建您的 x_ally_all 组合(无需在 combn 中创建许多组合,然后进行子集化),然后交叉连接您的组合:

x_1 = seq(0,49,2)
y_1 = seq(-90,-51,2)

#creating combinations
x_all <- do.call(rbind, lapply(head(seq_along(x_1), -4L), function(n) x_1[n + 0L:4L]))
y_all <- do.call(rbind, lapply(head(seq_along(y_1), -4L), function(n) y_1[n + 0L:4L]))
#or also 
#x_nc <- length(x_1)-4L
#x_all <- matrix(x_1[t(embed(seq_along(x_1), x_nc)[, x_nc:1L])], ncol=5L)

#cross join
cbind(
    x_all[rep(seq_len(nrow(x_all)), each=nrow(y_all)),],
    y_all[rep(seq_len(nrow(y_all)), times=nrow(x_all)),]
)

【讨论】:

【参考方案4】:

这是我的(不优雅的)解决方案:

# create empty list
    x_all_lst = list()

# put into list the `x_all` data.frame n times based on the number of y_all combinations (here 16)
    for (i in 1:nrow(y_all)) 
      x_all_lst[[i]] = x_all
    

# merge list
    x_all = do.call(rbind, x_all_lst)

# order list by column
    x_all = x_all[with(x_all, order(X1)), ]

# bind x_all and y_all columns
    x_y_all = cbind(x_all, y_all)

# remove row.names
    row.names(x_y_all) = NULL

【讨论】:

以上是关于查找两个不同长度的向量之间的所有组合的主要内容,如果未能解决你的问题,请参考以下文章

R-查找值的唯一排列

组合(cbind)不同长度的向量

查找不同长度的两个 DataFrame 之间的相似性

向量与子向量长度 n 的组合

不同长度向量的余弦相似度?

使用R语言将不同长度的向量合并为数据框