2016-08-22 3 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 ... сп, что мне нужно являются столбцы [a1 b1 c1 ], [a1, b1, c2], ..., [a1 b1 сп] ... [ап млрд сп]

Решение Предоставлено 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

Т.Л., др - комплексное решение:

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

Объяснение:

Предположим, у вас есть матрица a и b

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

Теперь у вас есть все комбинации столбцов а и б, как сцепленные строки с дубликатами удалены. Найти длины легко:

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

Вы можете преобразовать это дополнительно в список «Column кодовыми» кортежей с (несколько уродливым) список понимания:

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, и рекурсивно заполнял A все большим количеством элементов. Спасибо за ваши проблемы! – isebarn

+0

Рад, что он работает :) Обновлено с кратким решением «tl; dr» наверху независимо. Надеюсь, это добавит что-то полезное тоже :) –

+0

Спасибо, я ценю усилия! – isebarn

3

Ok , давайте посмотрим, понимаю ли я это. У вас есть n матрицы и хотите, чтобы все комбинации с одним столбцом от каждой из матриц n? Если да, то как насчет product() (для декартова произведения) из пакета Iterators?

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 Хорошо, я думаю, что я получаю сейчас. Я поправился с другим выстрелом в него, дайте мне знать, если это происходит с тем, что вы ищете. –

+1

прекрасный спасибо! – isebarn