熊猫:基于标头子字符串的部分数据透视

时间:2019-01-04 00:06:31

标签: python pandas pivot

我熟悉标准的Pandas枢轴功能,但是我要做的是有所不同-我不习惯使用pivot

设置代码:

import pandas as pd
import io

csvA = io.StringIO(u'''
month   chicken_a   chicken_b   chicken_c   turkey_a    turkey_b    turkey_c
1   10  20  30  1   2   3
2   11  22  33  101 202 303
''')

dfA = pd.read_csv(csvA, sep = '\t')

哪种产量:

   month  chicken_a  chicken_b  chicken_c  turkey_a  turkey_b  turkey_c
0      1         10         20         30         1         2         3
1      2         11         22         33       101       202       303

我想将'_a', '_b', and '_c'部分转到月份,但保留“鸡肉”和“火鸡”标题。最终结果将如下所示:

  month  chicken  turkey
0    1a       10       1
1    1b       20       2
2    1c       30       3
3    2a       11     101
4    2b       22     202
5    2c       33     303

'_a', '_b', '_c'部分将一如既往,并且会提前知道。

我可以通过for循环来破解它,但是我想知道是否还有更疯狂的方法。

3 个答案:

答案 0 :(得分:1)

我找到了一个我不喜欢的解决方案,但仍然觉得有些笨拙,但是没有循环,可以完成工作。我绝对愿意寻求更好的解决方案:

df  = dfA.set_index('month').stack().reset_index()

df['month_type']    = df['month'].astype(str) + df['level_1'].str[-1:]
df['level_1']       = df['level_1'].str[:-2]

df  = df.drop(['month'], axis = 1)
df  = df.pivot(index = 'month_type', columns = 'level_1', values = 0)
df  = pd.DataFrame(df.to_records())

答案 1 :(得分:1)

set_index列月份之后,您可以通过用MultiIndex拆分列名称来将列更改为'_'。使用stack之后,只需要将join的{​​{1}}简化为MultiIndex,然后再加上Index

reset_index

您会得到

#first convert month column to str, for later join
dfA['month'] = dfA['month'].astype(str)
#set month as index
dfA = dfA.set_index('month')
#change the column to MultiIndex using split
dfA.columns = pd.MultiIndex.from_tuples([col.split('_') for col in dfA.columns])
# stack
dfA = dfA.stack()
# simple index from the MultiIndex
dfA.index = pd.Index([''.join(ind) for ind in dfA.index], name='month')
#reset index
dfA = dfA.reset_index()

答案 2 :(得分:0)

pd.wide_to_long 在这种情况下效果很好:

dfB = pd.wide_to_long(dfA,['chicken','turkey'],i='month',j='suf',suffix='_\w')

结果

           chicken  turkey
month suf                 
1     _a        10       1
2     _a        11     101
1     _b        20       2
2     _b        22     202
1     _c        30       3
2     _c        33     303

然后您可以将两个索引连接成一个 month

dfB.reset_index(inplace = True)
dfB['month'] = dfB.astype({'month':'str'}).month + dfB.suf.str[1]
dfB.drop(columns='suf', inplace = True)

输出符合要求

  month  chicken  turkey
0   1a       10       1
1   2a       11     101
2   1b       20       2
3   2b       22     202
4   1c       30       3
5   2c       33     303