通过两个变量将熊猫的长宽重塑
- 2025-01-14 08:50:00
- admin 原创
- 173
问题描述:
我有长格式的数据并试图将其重塑为宽格式,但似乎没有使用 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:
这是另一个更加详细的解决方案,取自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'])
patient obs treatment score
0 1 1 0 6252
1 1 2 1 24243
2 1 3 0 2345
3 2 1 1 2342
4 2 2 0 23525
制作“宽”数据
df.pivot(index='patient', columns='obs', values='score')
obs 1 2 3
patient
1 6252.0 24243.0 2345.0
2 2342.0 23525.0 NaN
解决方案 2:
一个简单的枢轴可能足以满足您的需要,但这是我为重现您所需的输出所做的:
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)
解决方案 3:
Karl D 的解决方案触及了问题的核心。但我发现将所有内容旋转(由于.pivot_table
有两个索引列)然后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
解决方案 4:
虽然有点旧了,但我会将其发布给其他人。
你想要的可以实现,但你可能不想要它;)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
与使用单个函数作为 pivot 相比,使用 set_index 和 unstacking 的优势在于,您可以将操作分解为清晰的小步骤,从而简化调试。
解决方案 5:
pivoted = df.pivot('salesman', 'product', 'price')
第 192 页 Python 用于数据分析
解决方案 6:
一个老问题;这是对已经很优秀的答案的补充。pyjanitor中的pivot_wider可能有助于作为从长到宽重塑的抽象(它是pd.pivot的包装器):
# pip install pyjanitor
import pandas as pd
import janitor
idx = df.groupby(['Salesman', 'Height']).cumcount().add(1)
(df.assign(idx = idx)
.pivot_wider(index = ['Salesman', 'Height'], names_from = 'idx')
)
Salesman Height product_1 product_2 product_3 price_1 price_2 price_3
0 Knut 6 bat ball wand 5.0 1.0 3.0
1 Steve 5 pen NaN NaN 2.0 NaN NaN
相关推荐
热门文章
项目管理软件有哪些?
热门标签
曾咪二维码
扫码咨询,免费领取项目管理大礼包!
云禅道AD