web-dev-qa-db-ja.com

Pandas 2つの変数による長い形状から広い形状への変更

私は長い形式のデータを持っており、ワイドに再形成しようとしていますが、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コマンドを使用してこのようなことができると思います。

29
Luke

単純なピボットでニーズを満たすことができますが、これが目的の出力を再現するために行ったことです。

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)

@ルークは言った:

Stataは、reshapeコマンドを使用してこのようなことができると思います。

あなたはできますが、あなたが望む出力を得るためにスタタの形状を変更するにはグループ内のカウンタも必要だと思います:

     +-------------------------------------------+
     | 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)
32
Karl D.

少し古いですが、他の人にこれを投稿します。

あなたが望むものは達成できますが、おそらくあなたはそれを望まないはずです;)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とunstackingを使用する利点は、単一の関数をピボットとして使用することの利点は、操作を明確な小さなステップに分割できることです。これにより、デバッグが簡素化されます。

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

pg。 192 Pythonデータ分析用

9
chucklukowski

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'])

「ワイド」データを作成する

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

8
Charles Clayton

Karl Dのソリューションが問題の中心になります。ただし、すべてをピボットする方がはるかに簡単です(.pivot_table 2つのインデックス列があるため)、sortを選択し、MultiIndexを折りたたむ列を割り当てます。

df['idx'] = df.groupby('Salesman').cumcount()+1
df = df.pivot_table(index=['Salesman', 'Height'], columns='idx', 
                    values=['product', 'price'], aggfunc='first')

df = df.sort_index(axis=1, level=1)
df.columns = [f'{x}_{y}' for x,y in df.columns]
df = df.reset_index()

出力:

  Salesman  Height  price_1 product_1  price_2 product_2  price_3 product_3
0     Knut       6      5.0       bat      1.0      ball      3.0      wand
1    Steve       5      2.0       pen      NaN       NaN      NaN       NaN
3
ALollz