组合任意数量矩阵的每个列组合

时间:2016-08-22 16:06:46

标签: for-loop iterator combinations julia

我正试图想办法做一些“减少” 我有一个变化变化大小的矩阵数,例如

1 2 2 2 5 6...70 70
3 7 8 9 7 7...88 89

1 3 4
2 7 7
3 8 8
9 9 9

.
.

44 49 49 49 49 49 49
50 50 50 50 50 50 50
87 87 88 89 90 91 92

我需要做的事情(我希望我能够清楚地解释这一点)是将结合起来 这些矩阵中的列的组合,这意味着一列可能是

1
3
1
2
3
9

.
.
.

44
50
87

哪个会降低到

1
2
3
9
.
.
.
44
50
87

我之所以这样做是因为我需要找到最小的唯一组合列

我想要完成什么

对于那些感兴趣的人,我正在努力寻找最小的基因敲除 禁用反应。这里,每个矩阵代表一个反应,而列代表的指数 那些会阻止这种反应的基因。

该方法可以根据需要作为强力,因为这些矩阵很少变得非常大, 并且反应组合也不会很长

问题

我不能(据我所知)使用任意数量的迭代器创建一个for循环,并且 矩阵(禁用反应)是任意的。

澄清

如果我的矩阵A,B,C有列a1,a2 ... b1,b2 ... c1 ... cn我需要什么 列[a1 b1 c1],[a1,b1,c2],...,[a1 b1 cn] ... [a bn cn]

解决方案 礼貌为Michael Ohlrogge以下。

为了完整性,扩展他的答案

他的解决方案以

结束
MyProd = product(Array_of_ColGroups...)

完成工作

在他离开的地方继续前进

collection = collect(MyProd); #MyProd is an iterator
merged_cols = Array[] # the rows of 'collection' are arrays of arrays

for (i,v) in enumerate(collection)
    # I apologize for this line
    push!(merged_cols, sort!(unique(vcat(v...)))) 
end

# find all lengths so I can find which is the minimum
lengths = map(x -> length(x), merged_cols);

loc_of_shortest = find(broadcast((x,y) -> length(x) == y, merged_cols,minimum(lengths)))

best_gene_combos = merged_cols[loc_of_shortest]

2 个答案:

答案 0 :(得分:5)

tl; dr - 完整解决方案:

# example matrices
a = rand(1:50, 8,4); b = rand(1:50, 10,5); c = rand(1:50, 12,4);
Matrices = [a,b,c];

toJagged(x) = [x[:,i] for i in 1:size(x,2)];
JaggedMatrices = [toJagged(x) for x in Matrices];

Combined = [unique(i) for i in JaggedMatrices[1]];
for n in 2:length(JaggedMatrices)
  Combined = [unique([i;j]) for i in Combined, j in JaggedMatrices[n]];
end

Lengths         = [length(s) for s in Combined];
Minima          = findin(Lengths, min(Lengths...));
SubscriptsArray = ind2sub(size(Lengths), Minima);
ComboTuples     = [((i[j] for i in SubscriptsArray)...) for j in 1:length(Minima)]

<强>解释

假设您有矩阵ab

a = rand(1:50, 8,4);
b = rand(1:50, 10,5);

将它们表示为锯齿状数组,首先是列

A = [a[:,i] for i in 1:size(a,2)];
B = [b[:,i] for i in 1:size(b,2)];

使用列表推导连接所有列组合的行;当场删除重复:

Combined = [unique([i;j]) for i in A, j in B];

您现在拥有a和b的所有列组合,因为删除了重复项的连续行。轻松找到长度:

Lengths = [length(s) for s in Combined];

如果您有两个以上的矩阵,请在for循环中迭代执行此过程,例如:使用Combined矩阵代替a。例如如果你有一个矩阵c

c = rand(1:50, 12,4);
C = [c[:,i] for i in 1:size(c,2)];
Combined = [unique([i;j]) for i in Combined, j in C];

一旦将Lengths数组作为多维数组(与输入矩阵一样多的维度,其中每个维度的大小是每个矩阵中的列数),您可以找到与最低值对应的列组合(可以通过简单的ind2sub操作来实现多个组合:

Minima = findin(Lengths, min(Lengths...));
SubscriptsArray = ind2sub(size(Lengths), Minima)

(例如,对于具有3个输入矩阵的随机运行,我碰巧得到4个结果,最小长度为19. ind2sub的结果为([4,4,3,4,4],[3,3,4,5,3],[1,3,3,3,4])

您可以将其进一步转换为&#34;列组合&#34;具有(有点难看)列表理解的元组:

ComboTuples = [((i[j] for i in SubscriptsArray)...) for j in 1:length(Minima)]
# results in:
#   5-element Array{Tuple{Int64,Int64,Int64},1}:
#   (4,3,1)
#   (4,3,3)
#   (3,4,3)
#   (4,5,3)
#   (4,3,4)

答案 1 :(得分:3)

好的,让我们看看我是否理解这一点。您有n个矩阵,并希望所有n矩阵中的一列都有一个列?如果是这样,Iterators包中的product()(笛卡尔积)是怎么回事?

using Iterators

n = 3
Array_of_Arrays = [rand(3,3) for idx = 1:n] ## arbitrary representation of your set of arrays.
Array_of_ColGroups = Array(Array, length(Array_of_Arrays))

for (idx, MyArray) in enumerate(Array_of_Arrays)
    Array_of_ColGroups[idx] = [MyArray[:,jdx] for jdx in 1:size(MyArray,2)]
end

MyProd = product(Array_of_ColGroups...)

这将创建一个迭代器对象,然后您可以循环以考虑列的特定组合。