我有一个像这样的pandas数据框:
ts | thing_0 | qty_0 | thing_1 | qty_1 | thing_2 | qty_2
--------------------------------------------------------
1 | dog | 5 | cat | 3 | mouse | 1
2 | house | 6 | dog | 4 | cat | 2
...
我希望以thing
成为列并且qty
成为单元格值的方式对其进行转换。像这样:
ts | dog | cat | mouse | house
------------------------------
1 | 5 | 3 | 1 | 0
2 | 4 | 2 | 0 | 6
...
目前,我通过手动迭代df.values
数组手动进行此转换,但这非常慢。使用pandas意味着有更快的方法实现吗?
我看过df.pivot,但无法找到描述thing_0
和qty_0
之间关系的方法。
答案 0 :(得分:4)
您可以使用lreshape
来合并thing
和qty
列:
In [10]: pd.lreshape(df, {'thing':['thing_0','thing_1','thing_2',], 'qty':['qty_0','qty_1','qty_2']})
Out[10]:
ts thing qty
0 1 dog 5
1 2 house 6
2 1 cat 3
3 2 dog 4
4 1 mouse 1
5 2 cat 2
然后pivot
创建所需的DataFrame:
import pandas as pd
df = pd.DataFrame({'qty_0': [5, 6], 'qty_1': [3, 4], 'qty_2': [1, 2], 'thing_0': ['dog', 'house'], 'thing_1': ['cat', 'dog'], 'thing_2': ['mouse', 'cat'], 'ts': [1, 2]})
reshaped = pd.lreshape(df, {'thing':['thing_0','thing_1','thing_2',],
'qty':['qty_0','qty_1','qty_2']})
result = reshaped.pivot(index='ts', columns='thing', values='qty')
print(result)
产量
thing cat dog house mouse
ts
1 3.0 5.0 0.0 1.0
2 2.0 4.0 6.0 0.0
我认为jezrael's solution更好,因为它利用了你希望合并的列名的规律性。 df.columns.str.split('_', expand=True)
比
{'thing':['thing_0','thing_1','thing_2',],
'qty':['qty_0','qty_1','qty_2']}
lreshape
在您希望合并的列名称的情况下可能会有所帮助
是不规则的。
答案 1 :(得分:3)
您可以按str.split
从列创建MultiIndex
,然后按stack
和unstack
重新塑造:
df = df.set_index('ts')
df.columns = df.columns.str.split('_', expand=True)
df = df.stack().reset_index(level=1, drop=True)
.set_index('thing', append=True)['qty'].unstack(fill_value=0)
print (df)
thing cat dog house mouse
ts
1 3 5 0 1
2 2 4 6 0
使用pivot
代替unstack
的另一种解决方案:
df = df.set_index('ts')
df.columns = df.columns.str.split('_', expand=True)
df = df.stack().reset_index()
df = df.pivot(index='ts', columns='thing', values='qty').fillna(0).astype(int)
print (df)
thing cat dog house mouse
ts
1 3 5 0 1
2 2 4 6 0
第三个解决方案 - 为lreshape
动态创建字典,然后使用unstack
:
注意 - 必须对列进行排序,如果不添加df = df.sort_index(axis=1)
t = [x for x in df.columns if x.startswith('thing')]
q = [x for x in df.columns if x.startswith('qty')]
df = pd.lreshape(df, {'thing':t, 'qty':q})
.set_index(['ts','thing'])['qty'].unstack(fill_value=0)
print (df)
thing cat dog house mouse
ts
1 3 5 0 1
2 2 4 6 0
编辑:
lreshape
现在没有记录,但将来可能会删除(with pd.wide_to_long too)。
可能的解决方案是将所有3个函数合并为一个 - 也许melt
,但现在它没有实现。也许在一些新版本的熊猫中。然后我的答案会更新。