2015-10-23 3 views
1

в предыдущей ветке, блестящий ответ был задан следующей проблемой (Pandas: reshaping data). Цель состоит в том, чтобы изменить ряд панд, содержащий списки в панде dataframe следующим образом:python dataframe - функция лямбда X - возможна более эффективная реализация?

In [9]: s = Series([list('ABC'),list('DEF'),list('ABEF')]) 

In [10]: s 
Out[10]: 
0  [A, B, C] 
1  [D, E, F] 
2 [A, B, E, F] 
dtype: object 

должен быть придан так:

Out[11]: 
    A B C D E F 
0 1 1 1 0 0 0 
1 0 0 0 1 1 1 
2 1 1 0 0 1 1 

То есть dataframe создается где каждый элемент в списках серии становится столбец. Для каждого элемента в серии создается строка в фрейме данных. Для каждого элемента в списках 1 присваивается соответствующему столбцу данных (и 0 в противном случае). Я знаю, что формулировка может быть громоздкой, но, надеюсь, приведенный выше пример ясен.

Блестящая реакция пользователя Jeff (https://stackoverflow.com/users/644898/jeff) должен был написать этот простой, но мощный строку кода:

In [11]: s.apply(lambda x: Series(1,index=x)).fillna(0) 

Это превращает [10] в [11 отъезда].

Эта строка кода служила мне очень хорошо, однако я столкнулся с проблемами памяти с серией примерно 50 тыс. Элементов и около 100 тыс. Различных элементов во всех списках. Моя машина имеет 16 ГБ памяти. Прежде чем прибегать к более крупной машине, я хотел бы подумать о более эффективной реализации вышеприведенной функции.

Кто-нибудь знает, как повторно реализовать эту строку:

In [11]: s.apply(lambda x: Series(1,index=x)).fillna(0) 

, чтобы сделать его более эффективным, с точки зрения использования памяти?

+0

Как генерируется оригинальная серия? Лучше всего избегать наличия в нем списков. – chrisb

+0

хорошо вопрос. к сожалению, сериал создается с помощью утилизации - я не могу с этим поделать - я унаследовал набор данных от клиента. –

ответ

1

Вы можете попробовать ломать свой dataframe на куски и запись в файл, как вы идете, что-то вроде этого:

chunksize = 10000 
def f(df): 
    return f.apply(lambda x: Series(1,index=x)).fillna(0) 

with open('out.csv','w') as f: 
    f.write(df.ix[[]].to_csv()) #write the header 
    for chunk in df.groupby(np.arange(len(df))//chunksize): 
     f.write(f(chunk).to_csv(header=None)) 
1

Если использование памяти является проблемой, похоже, разреженным решением матрицы будет лучше. Панды действительно не имеет разреженную матрицу поддержки, но вы можете использовать scipy.sparse так:

data = pd.Series([list('ABC'),list('DEF'),list('ABEF')]) 

from scipy.sparse import csr_matrix 
cols, ind = np.unique(np.concatenate(data), return_inverse=True) 
indptr = np.cumsum([0] + list(map(len, data))) 
vals = np.ones_like(ind) 
M = csr_matrix((vals, ind, indptr)) 

Эта разреженная матрица теперь содержит те же данные, что и решение панд, но нули явно не сохраняются. Мы можем подтвердить это путем преобразования разреженной матрицы в dataframe:

>>> pd.DataFrame(M.toarray(), columns=cols) 
    A B C D E F 
0 1 1 1 0 0 0 
1 0 0 0 1 1 1 
2 1 1 0 0 1 1 

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

+0

jakevdp: потрясающий, потрясающий ответ. то, что используется для HOURS, занимает секунды. Ничто не является более мощным, чем хороший алгоритм! –

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