2016-07-24 4 views
0

Я имею дело с этапом предварительной обработки таблицы данных. Мой текущий код работает, но мне интересно, есть ли более эффективный способ.Есть ли более эффективный способ написать этот код Python?

Моя таблица данных выглядит следующим образом

object A object B  features of A  features of B 
    aaa   w   1     0 
    aaa   q   1     1 
    bbb   x   0     0 
    ccc   w   1     0 

для X было бы

[ (aaa, aaa, bbb, ccc), (w, q, x, w), (1, 1, 0, 1), (0, 1, 0, 0)] 

Сейчас я пишу код, чтобы сделать таблицу, которая включает в себя все комбинации всех возможных матча объект A & объект B (повторите комбинацию объекта A & объекта B без повторения), в то время как A & B сохраняет свои функции соответственно. Таблица будет выглядеть следующим образом: (строки со звездой являются добавленные строки)

object A object B  features of A  features of B 
    aaa   w   1     0 
    aaa   q   1     1 
* aaa   x   1     0 
--------------------------------------------------------- 
    bbb   x   0     0 
* bbb   w   0     0 
* bbb   q   0     1 
--------------------------------------------------------- 
    ccc   w   1     0 
* ccc   x   1     0 
* ccc   q   1     1 

Все данные по имени X Чтобы получить таблицу: Мой код выглядит следующим образом, но она работает очень медленно:

----------------------------------------- 
#This part is still fast 

#to make the combination of object A and object B with no repetition 

def uprod(*seqs): 
    def inner(i): 
     if i == n: 
      yield tuple(result) 
      return 
     for elt in sets[i] - seen: 
      seen.add(elt) 
      result[i] = elt 
      for t in inner(i+1): 
       yield t 
      seen.remove(elt) 

    sets = [set(seq) for seq in seqs] 
    n = len(sets) 
    seen = set() 
    result = [None] * n 
    for t in inner(0): 
     yield t 

#add all possibility into a new list named "new_data" 

new_data = list(uprod(X[0],X[1])) 

X_8v = X[:] 
y_8v = y[:] 

----------------------------------------- 
#if the current X_8v(content equals to X) does not have the match of object A and object B 
#in the list "new_data" 
#append a new row to the current X_8v 
#Now this part is super slow, I think because I iterate a lot 

for i, j in list(enumerate(X_8v[0])): 
    for k, w in list(enumerate(X_8v[1])): 
      if (X_8v[0][i], X_8v[1][k]) not in new_data: 
       X_8v[0] + (X_8v[0][i],) 
       X_8v[1] + (X_8v[1][k],) 
       X_8v[2] + (X_8v[2][i],) 
       X_8v[3] + (X_8v[3][k],) 
       X_8v[4] + (X_8v[4][i],) 
       X_8v[5] + (0,) 
       X_8v[6] + (0,) 
       y_8v.append(0) 

Есть ли какие-либо улучшения для кода выше?

Большое спасибо!

+0

@ Loïc даже не. –

+0

Это было бы намного проще с примером того, как выглядит структура данных (т. Е. 'X = ...'). – smarx

+0

Я запустил OP: http://pastebin.com/Acu5ZQND –

ответ

2

В реляционных терминах алгебры, это звучит, как вы хотите «особенность»

π[features of A, features of B] ((object A) X (object B))

т.е. полой проекта, в «особенности B» от перекрестного продукта «объект А» и «объект B».

Это очень естественно выразить в SQL.

Для Python, вы, вероятно, хотите, чтобы загрузить данные в несколько словарей, то есть object_a_to_features = {"aaa": 1, "bbb": 0} object_b_to_features = {"w": 0, "q": 1}

Затем вы хотите создать перекрестную продукт object_a_to_features.keys() и object_b_to_features.keys(), а затем для каждой строки просмотра функции в соответствующем словаре.

Посмотрите на product() from itertools.

Что-то вроде:

import itertools for pair in itertools.product(object_a_to_features.keys(), object_b_to_features.keys()): yield (pair[0], pair[1], object_a_to_features[pair[0]], object_b_to_features[pair[1]])

Пример вывода:

('aaa', 'q', 1, 1) ('aaa', 'w', 1, 0) ('bbb', 'q', 0, 1) ('bbb', 'w', 0, 0)

1

Предполагая, что данные на самом деле выглядит, как я думаю, что он делает, это должно делать то, что вы хотите, достаточно эффективно:

import itertools 

x = [('aaa', 'aaa', 'bbb', 'ccc'), ('w', 'q', 'x', 'w'), (1, 1, 0, 1), (0, 1, 0, 0)] 

a_list = set((x[0][i], x[2][i]) for i in range(len(x[0]))) 
b_list = set((x[1][i], x[3][i]) for i in range(len(x[1]))) 

for combination in itertools.product(a_list, b_list): 
    print(combination) 

# Output: 
# (('ccc', 1), ('w', 0)) 
# (('ccc', 1), ('x', 0)) 
# (('ccc', 1), ('q', 1)) 
# (('aaa', 1), ('w', 0)) 
# (('aaa', 1), ('x', 0)) 
# (('aaa', 1), ('q', 1)) 
# (('bbb', 0), ('w', 0)) 
# (('bbb', 0), ('x', 0)) 
# (('bbb', 0), ('q', 1)) 

Конечно, вы можете легко конвертировать данные обратно в порядке, первоначально было:

reordered = [[a[0], b[0], a[1], b[1]] for a, b in itertools.product(a_list, b_list)] 

for row in reordered: 
    print(row) 

# ['ccc', 'w', 1, 0] 
# ['ccc', 'x', 1, 0] 
# ['ccc', 'q', 1, 1] 
# ['aaa', 'w', 1, 0] 
# ['aaa', 'x', 1, 0] 
# ['aaa', 'q', 1, 1] 
# ['bbb', 'w', 0, 0] 
# ['bbb', 'x', 0, 0] 
# ['bbb', 'q', 0, 1] 

EDIT

Основываясь на комментарий ниже, если вы хотите, чтобы добавить столбец 1 указывает на «Эта строка был в исходном наборе данных »и 0, указывающий« Этот ряд не был в исходном наборе данных », попробуйте:

existing_combinations = set(zip(x[0], x[1])) 
reordered = [ 
    [a[0], b[0], a[1], b[1], 
    1 if (a[0], b[0]) in existing_combinations else 0 
    ] for a, b in itertools.product(a_list, b_list) 
] 

# Output: 
# ['ccc', 'x', 1, 0, 0] 
# ['ccc', 'q', 1, 1, 0] 
# ['ccc', 'w', 1, 0, 1] 
# ['bbb', 'x', 0, 0, 1] 
# ['bbb', 'q', 0, 1, 0] 
# ['bbb', 'w', 0, 0, 0] 
# ['aaa', 'x', 1, 0, 0] 
# ['aaa', 'q', 1, 1, 1] 
# ['aaa', 'w', 1, 0, 1] 
+0

Ничего себе, так приятно спросить здесь. Большое вам спасибо, –

+0

Ты бог. –

+0

Если у меня есть имена столбцов «существуют», то исходные данные имеют значение 1, а добавленные данные имеют значение 0, , которое сделало строку подобно ['ccc', 'w', 1, 0, 1], ['aaa ',' w ', 1, 0, 1], как я могу справиться с этим, когда хочу идентифицировать данные, добавленные или оригинальные? –

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