私は長い形式のデータを持っており、ワイドに再形成しようとしていますが、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コマンドを使用してこのようなことができると思います。
単純なピボットでニーズを満たすことができますが、これが目的の出力を再現するために行ったことです。
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)
少し古いですが、他の人にこれを投稿します。
あなたが望むものは達成できますが、おそらくあなたはそれを望まないはずです;)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を使用する利点は、単一の関数をピボットとして使用することの利点は、操作を明確な小さなステップに分割できることです。これにより、デバッグが簡素化されます。
pivoted = df.pivot('salesman', 'product', 'price')
pg。 192 Pythonデータ分析用
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')
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