Разверните pandas dataframe по категориальному столбцу - PullRequest
0 голосов
/ 20 февраля 2019

Я пытаюсь расширить фрейм данных, создав дополнительные столбцы, относящиеся к значению в одном категориальном столбце.Мой фрейм данных выглядит так:

Sample data

Исходя из значения столбца cluster, я хотел бы создать новый фрейм данных, который должен выглядеть следующим образом:

var1_clus0 , var1_clus1, ... var3_clus2

У меня огромный набор данных, поэтому я пытаюсь сделать это во вложенном цикле for, который отлично работает для 1-го значения столбца кластера, а все остальные имеют NaN.

Ниже приведен мой скрипт:

data_trans = pd.DataFrame()

for i in np.arange(0, len(varlist),1):
    for j in np.arange(0,6,1):
        data_trans[str(varlist[i]) + str("_clus_") + str(j)] = data[(data.segment_hc_print == j)][varlist[i]]

Код работает без ошибок и создает необходимый столбец.Но он анализирует только первое значение категориального столбца и помещает их в новый столбец в новом фрейме данных.Для всех других категориальных значений генерируется NAN.Что я делаю не так и как мне это исправить?

Sample output

Учитывая пример набора данных, который я привел, следующий желаемый вывод: пример вывода

1 Ответ

0 голосов
/ 20 февраля 2019

Поскольку у вас есть набор данных 2D, а у varX и clusX может быть несколько совпадений, вам нужно решить, что вы хотите делать с этими совпадениями?Я полагаю, вы хотите добавить их.Если это так, вы просматриваете либо фрейм данных со строкой заголовка и одной строкой данных, либо просто серию с индексом, являющимся вашим varX_clusX.

Следующий код сделает это:

# Setup
import pandas as pd
import numpy as np

df = pd.DataFrame({
    'var1'      : np.random.randint(0, 1000000, 1000000),
    'var2'      : np.random.randint(0, 1000000, 1000000),
    'var3'      : np.random.randint(0, 1000000, 1000000),
    'cluster'   : np.random.randint(0, 100, 1000000) 
    })

# Processing

# Setup the cluster column for string formatting.
df['cluster'] = 'clus' + df['cluster'].apply(str)

# Un-pivot the cluster column (I'm sure there's a better term)
df = df.set_index('cluster').stack().reset_index()

# Group by the unique combination of cluster / var and sum the values.
# This will generate a column named 0 - which I changed to 'values' just for readability.
df = df.groupby(['cluster','level_1']).sum().reset_index().rename(columns = {0 : 'values'})

# Create the formatted header you're looking for
df['piv'] = df['level_1'] + '_' + df['cluster']

# Final pivot to get the values to align with the the new headers
df = df.pivot(columns = 'piv', values = 'values').sum()

Пришло время на моей машине - примерно 1 с на миллион записей.Не уверен, как быстро вам это нужно.

Если вы не хотите добавлять все значения и есть произвольный индекс, вы можете упростить:

df['cluster'] = 'clus' + df['cluster'].apply(str)

df = df.set_index('cluster').stack().reset_index()

df['piv'] = df['level_1'] + '_' + df['cluster']

df = df.pivot(columns = 'piv', values = 0).fillna(0)

Это даст вам фрейм данныхдлина вашего начального набора данных х количество переменных и тонна нулей.

...