2016-08-22 70 views
2

我试图想出一个办法做了一定的“减量化” 我有一个不同矩阵不同大小,例如结合矩阵任意数量的每一列组合

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 

为什么我这样做的原因是因为我需要找到最小的唯一合并塔

什么我试图完成

对于那些感兴趣的,我试图找到最小的一组基因敲除 禁用反应。在这里,每个矩阵代表一个反应,而列代表将禁止该反应的基因的指数。

的方法可以是如蛮力根据需要,因为这些矩阵很少变成压倒性大, 并将反应组合不会很长或者

问题

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

澄清

如果我有矩阵A,B,C与列A1,A2 ...... B1,B2 ...... C1 ... CN什么,我需要 是列[A1 B1 C1 ],[A1,B1,C2],...,[A1 B1 CN] ... [一个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] 

回答

5

TL;博士 - 完整的解决方案:

# 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]; 

如果有两个以上的矩阵,在反复进行此过程循环,例如通过使用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]; 

一旦你的长度数组作为多维阵列(如许多尺寸输入矩阵,其中每个维度的大小是列中的每个矩阵中的数),就可以找到对应于最低值的列的组合(很可能有多于一个的组合以上),通过简单的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])

您可以进一步将其转换为“栏目联合”的元组用(有点丑陋)列表理解列表:

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

精美的作品!我迭代了一个包含B..N的数组数组,并递归地填充了越来越多的元素。感谢您的麻烦! – isebarn

+0

很喜欢它的工作原理:) 无论是在顶部简洁的“tl; dr”解决方案更新。希望这会增加一些有用的东西:) –

+0

谢谢,我欣赏努力! – isebarn

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...) 

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

+0

@isebarn OK,我想我现在就买下。我用另一个镜头对它进行了修正,让我知道如果这是你正在寻找的东西。 –

+1

美丽的谢谢你! – isebarn