2017-02-10 21 views
1

У меня есть список списков, которые я хочу превратить в dataframe, сохраняя их индекс в исходном списке.Список списков в dataframe в pandas

x = [["a", "b", "c"], ["A", "B"], ["AA", "BB", "CC"]] 

Я могу сделать это с цикл, как это:

result = [] 
for id, row in enumerate(x): 
    d = pd.DataFrame({"attr": row, "id": [id]*len(row)}) 
    result.append(d) 
result = pd.concat(result, ignore_index=True) 

или эквивалентное выражение генератора:

pd.concat((pd.DataFrame({"attr": row, "id": [id]*len(row)}) 
      for id, row in enumerate(x)), ignore_index=True) 

И работает отлично, производя кадр данных, как:

id attr 
0 0 a 
1 0 b 
2 0 c 
3 1 A 
4 1 B 
5 2 AA 
6 2 BB 
7 2 CC 

Но это чувствует например, должен быть более «panda-esque» способ сделать это, чем с шаблоном list-loop-append или эквивалентным генератором.

Могу ли я создать фрейм данных выше с помощью вызова pandas, т. Е. Без понимания for или python?

(желательно также более быстрое решение: в «жанрах» данных киноинтерфейса, установленном в https://grouplens.org/datasets/movielens/, требуется> 4 секунды, чтобы сгладить список жанров на фильм, хотя всего всего 20 тыс. Записей ...)

+0

'Stack()' является то, что вы ищете –

+0

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

ответ

0

Мне кажется, что вам нужен быстрый способ сгладить список x, а также создать еще один список идентификаторов. Существует хорошо прочитанное сообщение об эффективности flattening lists.

Вы можете просто настроить основное упрощение списка, чтобы быстро генерировать свои идентификаторы.

x = [["a", "b", "c"], ["A", "B"], ["AA", "BB", "CC"]] 
attr = [attr for sublist in x for attr in sublist] 
id = [id for sublist in [[i]*len(r) for i,r in enumerate(x)] for id in sublist] 
df = pd.DataFrame({'attr': attr, 'id': id }) 
df 
>>> 
    attr id 
0 a 0 
1 b 0 
2 c 0 
3 A 1 
4 B 1 
5 AA 2 
6 BB 2 
7 CC 2 

# Testing the time to flatten 20k nested lists 
import timeit 

setup = ''' 
vals = [[1], [1,2], [1,2,3], [1,2,3,4]]*5000 
lots_of_ids = [attr for sublist in [[i]*len(r) for i,r in enumerate(vals)] for attr in sublist] 
''' 

print min(timeit.Timer(setup=setup).repeat(10)) 
>>> 0.0471019744873 
1

Я считаю, что stack() является то, что вы ищете:

pd.DataFrame(x).stack().reset_index().drop('level_1', axis=1)