2017-07-07 79 views
4

我有一个这样的熊猫数据帧:熊猫:转换对列于细胞

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阵列,但是这是非常缓慢的。有没有更快的方式来实现这与熊猫的手段?

我看过df.pivot,但找不到描述thing_0qty_0之间关系的方法。

回答

3

您可以通过str.split创建列MultiIndex,然后通过stackunstack重塑:

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,但现在它不实现。也许在一些新版熊猫中。然后我的答案将被更新。

4

你可以使用lreshape聚结thingqty列:

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以创建所需的数据框:

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可能是在你想合并 是不规则的列名的情况下有用的少重复。