2016-11-10 3 views
4

Я запускаю некоторые модели в Python с подмножеством данных по категориям.Более быстрый способ удаления неиспользуемых категорий в пандах?

Для использования в памяти и предварительной обработки все категориальные переменные сохраняются как тип данных категории.

Для каждого уровня категориальной переменной в столбце «группа за» я запускаю регрессию, где мне нужно сбросить все свои категориальные переменные на те, которые присутствуют в этом подмножестве.

В настоящее время я делаю это с использованием .cat.remove_unused_categories(), что занимает почти 50% от моего общего времени выполнения. На данный момент худшим нарушителем является моя колонка группировки, другие не занимают столько времени (как я полагаю, не так много уровней для снижения).

Вот упрощенный пример:

import itertools 
import pandas as pd 
#generate some fake data 
alphabets = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z'] 
keywords = [''.join(i) for i in itertools.product(alphabets, repeat = 2)] 
z = pd.DataFrame({'x':keywords}) 

#convert to category datatype 
z.x = z.x.astype('category') 

#groupby 
z = z.groupby('x') 

#loop over groups 
for i in z.groups: 
    x = z.get_group(i) 
    x.x = x.x.cat.remove_unused_categories() 
    #run my fancy model here 

На моем ноутбуке, это занимает около 20 секунд. для этого небольшого примера мы можем преобразовать в str, а затем вернуться в категорию для ускорения, но мои реальные данные имеют не менее 300 строк на группу.

Можно ли ускорить этот цикл? Я пробовал использовать x.x = x.x.cat.set_categories(i), который занимает аналогичное время, и x.x.cat.categories = i, который запрашивает столько же категорий, сколько я начал.

+1

вы можете попробовать это: 'х = z.get_group (I) .astype ({ 'х': 'ул'}). Astype ({ 'х':» category '}) 'и удалите эту строку:' xx = xxcat.remove_unused_categories() '? интересно, будет ли это быстрее ... – MaxU

+0

ускоряет этот пример, но мои реальные данные имеют 3-400 строк по группе, а в этом случае преобразование строк медленнее. – jeremycg

ответ

6

Ваша проблема в том, что вы назначаете z.get_group(i) на номер x. x теперь является копией части z. Ваш код будет работать нормально с этим изменением

for i in z.groups: 
    x = z.get_group(i).copy() # will no longer be tied to z 
    x.x = x.x.cat.remove_unused_categories() 
+0

, но он все равно скопирует все категории из родительского DF - вы думаете, что это будет намного быстрее? – MaxU

+1

Я не уверен, что делает OP! Поэтому я должен им доверять и «здесь моя модная модель». Я запускал этот код, и он был очень медленным, потому что он выводил предупреждения SetWithCopy. Я меняю эту строку, и она завершается в кратчайшие сроки. – piRSquared

+0

Теперь я запустил его, это наверняка проблема с моим исходным кодом. Благодаря миллиону - вы можете видеть, что проблема все еще существует, если мы увеличиваем 'repeat = 2' до 3 в построении данных, но это уменьшилось с 0,5 от времени выполнения до 0,05. – jeremycg

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