Pandas длинный для широкой перестройки

У меня есть данные в длинном формате и я пытаюсь переформатировать в широкие, но, похоже, нет простого способа сделать это, используя melt/stack/unstack:

Salesman  Height   product      price
  Knut      6        bat          5
  Knut      6        ball         1
  Knut      6        wand         3
  Steve     5        pen          2

становится:

Salesman  Height    product_1  price_1  product_2 price_2 product_3 price_3  
  Knut      6        bat          5       ball      1        wand      3
  Steve     5        pen          2        NA       NA        NA       NA

Я думаю, что Stata может сделать что-то подобное с помощью команды reshape.

Ответы

Ответ 1

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

df['idx'] = df.groupby('Salesman').cumcount()

Просто добавление внутри группового счетчика/индекса даст вам большую часть пути, но метки столбцов не будут такими, какие вы хотели:

print df.pivot(index='Salesman',columns='idx')[['product','price']]

        product              price        
idx            0     1     2      0   1   2
Salesman                                   
Knut         bat  ball  wand      5   1   3
Steve        pen   NaN   NaN      2 NaN NaN

Чтобы приблизиться к вашему желаемому результату, я добавил следующее:

df['prod_idx'] = 'product_' + df.idx.astype(str)
df['prc_idx'] = 'price_' + df.idx.astype(str)

product = df.pivot(index='Salesman',columns='prod_idx',values='product')
prc = df.pivot(index='Salesman',columns='prc_idx',values='price')

reshape = pd.concat([product,prc],axis=1)
reshape['Height'] = df.set_index('Salesman')['Height'].drop_duplicates()
print reshape

         product_0 product_1 product_2  price_0  price_1  price_2  Height
Salesman                                                                 
Knut           bat      ball      wand        5        1        3       6
Steve          pen       NaN       NaN        2      NaN      NaN       5

Изменить: если вы хотите обобщить процедуру на большее количество переменных, я думаю, вы могли бы сделать что-то вроде следующего (хотя это может быть недостаточно эффективно):

df['idx'] = df.groupby('Salesman').cumcount()

tmp = []
for var in ['product','price']:
    df['tmp_idx'] = var + '_' + df.idx.astype(str)
    tmp.append(df.pivot(index='Salesman',columns='tmp_idx',values=var))

reshape = pd.concat(tmp,axis=1)

@Luke сказал:

Я думаю, что Stata может сделать что-то подобное с помощью команды reshape.

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

     +-------------------------------------------+
     | salesman   idx   height   product   price |
     |-------------------------------------------|
  1. |     Knut     0        6       bat       5 |
  2. |     Knut     1        6      ball       1 |
  3. |     Knut     2        6      wand       3 |
  4. |    Steve     0        5       pen       2 |
     +-------------------------------------------+

Если вы добавите idx, вы можете изменить форму в stata:

reshape wide product price, i(salesman) j(idx)

Ответ 2

Немного старый, но я отправлю это для других людей.

То, что вы хотите, может быть достигнуто, но вы, вероятно, не захотите этого;) Pandas поддерживает иерархические индексы для строк и столбцов. В Python 2.7.x...

from StringIO import StringIO

raw = '''Salesman  Height   product      price
  Knut      6        bat          5
  Knut      6        ball         1
  Knut      6        wand         3
  Steve     5        pen          2'''
dff = pd.read_csv(StringIO(raw), sep='\s+')

print dff.set_index(['Salesman', 'Height', 'product']).unstack('product')

Создает более удобное представление, чем то, что вы искали

                price             
product          ball bat pen wand
Salesman Height                   
Knut     6          1   5 NaN    3
Steve    5        NaN NaN   2  NaN

Преимущество использования set_index и отладки по сравнению с одной функцией в качестве сводной точки состоит в том, что вы можете разбить операции на четкие небольшие шаги, что упрощает отладку.

Ответ 3

pivoted = df.pivot('salesman', 'product', 'price')

пг. 192 Python для анализа данных

Ответ 4

Здесь другое решение, более сложное, взятое из сайта Chris Albon.

Создайте "длинный" фрейм данных

raw_data = {'patient': [1, 1, 1, 2, 2],
                'obs': [1, 2, 3, 1, 2],
          'treatment': [0, 1, 0, 1, 0],
              'score': [6252, 24243, 2345, 2342, 23525]}

df = pd.DataFrame(raw_data, columns = ['patient', 'obs', 'treatment', 'score'])

RRfjY.png

Сделайте "широкие" данные

df.pivot(index='patient', columns='obs', values='score')

agIMh.png

Ответ 5

Переформатирование документов здесь

Вы ищете pd.wide_to_long() (который является прямым аналогом команды stata)