2015-05-18 2 views
1

У меня есть следующий набор данных: dfgroupby.sum() разреженная матрица в пандах или SciPy: ищу производительность

import numpy.random 
import pandas 

cat = pandas.Series(numpy.random.random_integers(0,400,1000000)) 
ids = pandas.Series(numpy.random.random_integers(0,10000,1000000)) 
team = pandas.Series(numpy.random.random_integers(0,1,1000000)) 
df = pandas.concat([ids,cat,team],axis=1) 
df.columns = ['ids','cat','team'] 

Обрати внимание, что есть только 400 различные категории в cat колонки. Соответственно, я хочу подготовить набор данных для классификации машинного обучения, т. Е. Создать один столбец для каждого отдельного значения категории от 0 до 400, а для каждой строки - записать 1, если идентификатор имеет соответствующую категорию, а 0 в противном случае. Моя цель состоит в то, чтобы сделать GroupBy ids и просуммировать 1 для каждой категории колонке следующим образом:

df2 = pandas.get_dummies(df['cat'], sparse=True) 
df2['ids'] = df['ids'] 
df3 = df2.groupby('ids').sum() 

Моя проблема заключается в том, что groupby.sum() очень и очень долго, слишком долго (более 30 минут). Поэтому мне нужна другая стратегия, чтобы сделать мои расчеты. Вот вторая попытка.

from sklearn import preprocessing 
import numpy 

text_encoder = preprocessing.OneHotEncoder(dtype=numpy.int) 
X = text_encoder.fit_transform(df.drop(['team','ids'],axis=1).values).astype(int) 

Но тогда, X является разреженным SciPy матрица. Здесь у меня есть два варианта: либо найти способ groupby.sum() эффективно на этой редкой SciPy матрицы, или преобразовать его в реальную матрицу Numpy с .toarray() следующим образом:

X = X.toarray() 
df2 = pandas.DataFrame(X) 
df2['ids'] = df['ids'] 
df3 = df2.groupby('ids').sum() 

Сейчас проблема заключается в том, что много памяти теряется из-за .toarray(). И groupby.sum(), безусловно, занимает много памяти.

Так что мой вопрос: есть ли умный способ решить мою проблему, используя SPARSE MATRIX с ЭФФЕКТИВНЫМ ВРЕМЕНИ для groupby.sum()?

+0

Это просто пример? Моя версия панд должна быть старой, поэтому я не могу добавить разреженный аргумент при создании df2 с помощью get_dummies(). Но тогда 'df3 = df2.groupby ('ids'). Sum()' очень быстрая, хотя на самом деле она занимает довольно много памяти (c. 6Go). Если groupby работает медленнее с sparse_matrix .. решение может состоять в том, чтобы избежать этого, сортируя данные по идентификаторам, находя, где каждый id запускается и останавливается, а затем просто .sum (0) на срезах разреженной матрицы – etna

+0

Просто для того, чтобы развернуть бит , сортировка будет 'df.sort ('ids', inplace = True)' и 'df.groupby ('ids'). size()' расскажет вам, сколько строк нарезки для каждого последующего 'id' в вашем разреженном матрица. Нарезка должна работать классическим способом, например. 'X [0:95,:]. Sum (0)', если имеется 95 строк, т. Е. Характеристики для первого id. – etna

+0

Вы изучали редкие документы pandas? http://pandas.pydata.org/pandas-docs/dev/sparse.html – hpaulj

ответ

2

EDIT: На самом деле это работа для pivot_table(), так как только ваша df создана:

df_final = df.pivot_table(cols='cat', rows='ids', aggfunc='count') 
df_final.fillna(0, inplace = True) 

Для записи, но бесполезно: после моего замечания по этому вопросу:

import numpy.random 
import pandas 
from sklearn import preprocessing 

cat = pandas.Series(numpy.random.random_integers(0,400,1000000)) 
ids = pandas.Series(numpy.random.random_integers(0,10000,1000000)) 
team = pandas.Series(numpy.random.random_integers(0,1,1000000)) 
df = pandas.concat([ids,cat,team],axis=1) 
df.columns = ['ids','cat','team'] 

df.sort('ids', inplace = True) 

text_encoder = preprocessing.OneHotEncoder(dtype=numpy.int) 
X = text_encoder.fit_transform(df.drop(['team','ids'],axis=1).values).astype(int) 

se_size = df.groupby('ids').size() 

ls_rows = [] 
row_ind = 0 
for name, nb_lines in se_size.iteritems(): 
    ls_rows.append(X[row_ind : row_ind + nb_lines,:].sum(0).tolist()[0]) 
    row_ind += nb_lines 
df_final = pandas.DataFrame(ls_rows, 
          index = se_size.index, 
          columns = text_encoder.active_features_) 
+0

Спасибо за ваш ответ. Тем не менее, полученная вами матрица не выглядит как get_dummies (индекс должен быть df ['ids']. Unique(), а столбцы должны быть по одному для разных значений кота. Кроме того, вы не делаете .sum(), поэтому я не уверен, что этот ответ хорош. – sweeeeeet

+0

И, наконец, итерация по группе обычно очень медленная. Я пробовал свой код с 'df_final.loc [cat, name] + = 1', и это занимает слишком много времени. – sweeeeeet

+0

Я отредактировал код так, чтобы вы получили идентификаторы в виде строк и категорий в виде столбцов. Он не использует sum(), потому что я использую другую логику. Я создаю конечный dataframe с 0s и заполняю его: с помощью 'name', я перебираю ids и для каждого id/name: инструкция 'df_final.loc [cat, name] = 1' пишет 1 для категорий, имеющих отношение к этому id в столбце, посвященном этому id. Наконец, я просто переставляю dataframe, чтобы получить идентификаторы в виде строк и категорий в виде столбцов. Он работает через несколько секунд на моем компьютере, в то время как это не так. – etna

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