Повышение производительности groupby()

#python #pandas #group-by #pandas-groupby

#питон #панды #группа-по #панды-групповые

Вопрос:

Исходный кадр данных является:

 import pandas as pd array = {'id': [1, 1, 1, 1, 2, 3],  'color': ['yellow', 'red', 'yellow', 'red', 'yellow', 'white']} df = pd.DataFrame(array) df  id color 1 yellow 1 red 1 yellow 1 red 2 yellow 3 white  

Я преобразовал его в следующий фрейм данных с помощью get_dummies:

 df = pd.get_dummies(df, prefix='', prefix_sep='') df   id red white yellow 0 1 0 0 1 1 1 1 0 0 2 1 0 0 1 3 1 1 0 0 4 2 0 0 1 5 3 0 1 0  

который я хочу сгруппировать по() столбцу «идентификатор»:

 df.groupby(['id']).max()   red white yellow id  1 1 0 1 2 0 0 1 3 0 1 0  

Однако мой исходный кадр данных состоит из 8000 строк на 1 500 000 столбцов, что делает эту операцию слишком медленной.

Есть какие-нибудь идеи о том, как сделать это быстрее?

Комментарии:

1. Какова ваша модель данных, если ваш фрейм данных настолько широк?

2. Что вы подразумеваете под моделью данных?

3. Сколько у вас групп в 8000 строк?

4. Я обновил свой ответ

5. помогает ли это: : df.groupby([*df]).size().clip(upper=1).unstack('color', fill_value=0)

Ответ №1:

Обновить

Основываясь на вашем исходном фрейме данных, я бы создал уникальный фрейм данных и свернул (или закодировал) его позже. Таким образом, вы полностью избегаете любого последующего агрегирования.

 df_unique = df.drop_duplicates() df_unique["val"] = 1 df_unique  id color val 0 1 yellow 1 1 1 red 1 4 2 yellow 1 5 3 white 1  df_unique.set_index("id").pivot(columns="color").fillna(0)  red white yellow id  1 1.0 0.0 1.0 2 0.0 0.0 1.0 3 0.0 1.0 0.0  

Варианты кодирования

Пожалуйста, попробуйте изменить форму ваших данных (что также отнимает много времени), но может быть быстрее, чем ваш текущий широкий формат:

 # first approach using melt.groupby.max  pd.melt(df, id_vars = 'id').groupby(["id", "variable"]).max()  # second approach using melt.sort.groupby.first pd.melt(df, id_vars = 'id').sort_values(by="variable", ascending=True).groupby(["id", "variable"]).first()  

Вы можете запустить это позже, чтобы снова сохранить желаемую форму:

 melted_and_aggregated_df.reset_index(level=["variable"]).pivot(columns=["variable"], values="value")  

Размер Данных

Помимо чистой эффективности кодирования, постарайтесь уменьшить объем ваших данных.

  • В случае, если есть группы, в которых есть только одна строка, вы должны использовать подход max/first только для других групп, а затем объединить результаты.
  • Существует ли на самом деле 1,5 миллиона цветов? Звучит грандиозно. Вам действительно нужны все они или их можно предварительно уменьшить/агрегировать?

Комментарии:

1. Спасибо!!! Вы уверены, что таяние происходит быстрее? Применение его к короткому кадру данных, который я опубликовал выше, занимает 3 мс, когда исходная функция groupby() занимает 1 мс

2. Цвета — это всего лишь пример. Данные реального мира закодированы по-другому

3. Нет, я не уверен. Это просто еще один способ решения этой проблемы. Основной акцент должен делаться на сокращении объема ваших данных до их агрегирования. Я сомневаюсь, что есть вариант, который был бы очень быстрым, учитывая большой размер данных

4. нет… плавление не должно быть быстрее, вы увеличиваете количество строк, что не обеспечивает никакой эффективности. Я бы предположил, что более быстрым решением, чем groupby, должно быть решение, которое уменьшает количество строк и позволяет выполнять векторизованные операции со столбцами

5. Можете ли вы вместо этого поделиться исходным кадром данных, поделиться своим конечным ожидаемым результатом