2016-08-22 74 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