2016-10-14 3 views
-1

У меня есть большие данные, такие как:Python матрица сравнения

{'a_1':0b110000, 
'a_2':0b001100, 
'a_3':0b000011, 
'b_1':0b100100, 
'b_2':0b000001, 
'c_1':0b100000,} 

и так далее ... структура данных может быть реорганизовано и больше, чтобы показать, что я хочу достичь. Строки «a» никогда не будут перекрываться по их подстрокам. Что было бы лучшим способом, чтобы получить наилучшие комбинации из двух (ab, ac) или трех (abc) или более строк с точки зрения большинства совпадающих значений? Надежда, вопросы понятны как-то, трудно описать:/ Возможно, некоторые операции с матрицами numpy?

Дополнительная информация: Возможные комбинации двух элементов: ab, ac, bc. ab проверит строки a (a_1, a_2, a_3) на строки b (b_1, b_2) друг друга. a_1 & b_1 означает 0b110000 & 0b100100 и дал бы один результат. a_1 & b_2 означает 0b110000 & 0b000001 и не даст никакого результата. Это будет описание решения с помощью циклов, но оно очень медленное, особенно с комбинациями 8 или около того (не охваченными примерами данных).

может быть более четкой структуры данных:

{'a': [0b110000, 
     0b001100, 
     0b000011], 
'b': [0b100100, 
     0b000001], 
'c': [0b100000]} 

Позвольте мне показать, как я делаю эти расчеты до сих пор. Структура данных является своего рода разные, как я попытался начать этот вопрос с «Я думал, что» лучше структура ...

data = {'a':[1,1,2,2,3,3], 
     'b':[4,5,5,5,4,5], 
     'c':[6,7,7,7,6,7]}  

combine_count = 3 
for config in combinations(['a','b','c'],combine_count): 
    ret = {} 
    for index,combined in enumerate(zip(*tuple(data.get(k) for k in config))): 
     ret.setdefault(combined, []).append(index) 

for k,v in ret.items(): 
    score = len(v) 
    if score >= 2: 
     print(k,score) 

моя проблема состоит в том, что прежде всего процесс построения в сочетании с большим combine_count занимает много времени. данные, конечно, намного больше. Он имеет около 231 ключ со списками каждая длиной ~ 60000. Кроме того, потребление ОЗУ слишком велико.

+0

используйте пример данных, чтобы точно показать, какого результата вы достигнете. (ab, ac) и (abc), по-видимому, появились из ниоткуда и напрямую не связаны с вашими большими данными. – paddyg

+0

добавил дополнительную информацию. Надеюсь, это поможет. –

+0

, то это приведет к появлению a1 & b1-> 16, a1 & b2-> 0, a2 & b1-> 4, a2 & b2-> 0, a3 & b1-> 0, a3 & b2-> 1, которые будут совпадать и совпадать? Для вашей тройной версии оценка будет, скажем, a1 & b1 | a1 & c1 | b1 & c1? – paddyg

ответ

1

Не уверен в вашей тройной оценке *, но вы можете изменить это, чтобы делать то, что вы хотите. Я предполагаю, что вы будете перебирать комбинации A, B, C и т.д.

#!/usr/bin/python 
import numpy as np 
import random 
import time 

A = [np.random.randint(0, 2**15, random.randint(1, 5)) + 2**16 for i in range(231)] 
best_score = 0 
tm = time.time() 
for i, a in enumerate(A): 
    for j, b in enumerate(A[1:]): 
    for k, c in enumerate(A[2:]): 
     an, bn, cn = len(a), len(b), len(c) #some shortcuts 

     a_block = np.broadcast_to(a.reshape(an, 1, 1), (an, bn, cn)) 
     b_block = np.broadcast_to(b.reshape(1, bn, 1), (an, bn, cn)) 
     c_block = np.broadcast_to(c.reshape(1, 1, cn), (an, bn, cn)) 

     all_and = c_block & b_block & a_block 

     all_score = ((all_and & 1) + 
        ((all_and >> 1) & 1) + 
        ((all_and >> 2) & 1) + 
        ((all_and >> 3) & 1) + 
        ((all_and >> 4) & 1) + 
        ((all_and >> 5) & 1)) 
     ix = np.unravel_index(np.argmax(all_score), (an, bn, cn)) 
     if all_score[ix] > best_score: 
     print(i,j,k, ix, all_score[ix], a_block[ix], b_block[ix], c_block[ix]) 
     best_score = all_score[ix] 
     best_abc = (i, j, k) 
     best_ix = ix[:] 

print(time.time() - tm) 
print(best_score) 
print(best_abc) 
print(best_ix) 
''' gives 
0 0 0 (0, 2, 0) 2 95038 76894 78667 
0 0 1 (0, 3, 1) 3 95038 70262 96242 
0 0 2 (0, 2, 0) 4 95038 76894 96255 
0 3 2 (0, 0, 0) 5 95038 96255 96255 
4 3 2 (0, 0, 0) 6 96255 96255 96255 
871.6093053817749 
6 
(4, 3, 2) 
(0, 0, 0) 
''' 

EDIT * Я думаю, что этот код делает: найти место (и ценность) максимума между a1 & b1 & c1, a2 & & b1 c1, a3 & & b1 c1, a1 & b2 & c1 и т.д., которые, возможно, отличается от a1 & & b1 c1 | a2 & b1 & c1 | a3 & b1 & c1 | a1 & b2 & c1

EDIT2 Более подробно показан процесс итерации по псевдодальному набору данных. a, b, c - массивы длиной от 1 до 5, но numpy randint не может генерировать случайные числа 60000 бит в длину, также я не пытался обеспечить, чтобы все числа были уникальными (что было бы довольно легко сделать). Это занимает около 15 м на этом не очень мощном ноутбуке, так что дает вам отправную точку для сравнения.

Способ ускорения процесса может заключаться в том, чтобы ограничить сравнение только двумя, то есть a, b, чтобы начать и сохранить список высоких показателей, затем пройти через каждую из этих комбинаций & против всех других записей в чтобы выбрать самый высокий выигрыш в трех направлениях и.

+0

Спасибо за ваш ответ :). Мне нужно время, чтобы проверить это. Но можете ли вы объяснить вывод, который он дает? Я не совсем уверен, что это значит. Кстати, может быть, я должен отметить, что входные данные не обязательно должны быть этими двоичными числами. Они просто отмечают позиции разных значений a, b, c. –

+0

Вот выход из вашего ответа: [[[1 0 0 0] [0 0 0 0]] [[0 0 0 1] [0 0 0 0]] [[0 0 0 0] [0 0 0 0]]] (0, 0, 0) –

+0

@SvenLange Хорошо, так что, возможно, это был не такой явный пример. Я изменил пару чисел, чтобы дать двухбитное совпадение не на 0,0,0 и добавил больше объяснений. Надеюсь, теперь это понятно. (также переименовал all_or в all_and, не знаю, почему я назвал его «или» раньше!) – paddyg

Смежные вопросы