首页 > 解决方案 > 使用 stack/unstack 重塑数据框

问题描述

我有一个看起来像这样的数据框:

df1 = pd.DataFrame({'Type' : ['Q','A','A'], 'Fields': ['Q1','Pre','Post'],'ChildA' : [0,3,5],'ChildB' : [0,2,3]})

    ChildA  ChildB Fields Field_Type
 0       0       0     Q1          Q
 1       3       2    Pre          A
 2       5       3   Post          A

总共有大约200个左右的孩子和50个左右的问题。我想要的是看起来像这样的东西:

      Name     Question    Pre     Post
   0  ChildA   Q1          3       5
   1  ChildB   Q1          2       3
   2  ChildA   Q2          1       4
   3  ChildB   Q2          3       3

但我不确定如何最好地解决这个问题,我已经尝试过stackpivot但两者都会返回ValueError: Index contains duplicate entries, cannot reshape,或者当它工作时,它不是我需要的格式,或者可以朝着正确的格式工作。到目前为止,我最接近的是使用转置df2 = df1[0:3].T,只要我一次取 3 行,它就可以工作,但这似乎非常低效,我知道必须有更好的方法使用枢轴或堆栈/取消堆栈。

也许这会涉及到一些多重索引,所以我很喜欢,stack因为pivot它给出了各种各样的问题,比如Exception: Data must be 1-dimensional我什么时候会尝试说

df1.pivot(columns='Name',values=['Ben','Jack'])

任何帮助是极大的赞赏!

标签: pandasdataframestackpivotmulti-index

解决方案


实际上,您在一个数据框中有两组数据。加上答案没有他们是针对哪个问题的

  1. np.where使用和的组合对每个答案提出一个问题fillna()
  2. 只有答案索引它所以转置是有意义的
  3. stack()问题再次成为专栏
import numpy as np
df1 = pd.DataFrame({'Type' : ['Q','A','A'], 'Fields': ['Q1','Pre','Post'],'ChildA' : [0,3,5],'ChildB' : [0,2,3]})

maskq = df1["Type"]=="Q"
# need to get question against each answer
df1 = (df1
 .assign(Question=lambda x: np.where(x["Type"]=="Q", x["Fields"], np.nan))
 .assign(Question=lambda x: x["Question"].fillna(method="ffill"))
)
# now take just questions and organise as required
df1 = df1.loc[~maskq, [c for c in df1.columns if c!="Type"]].set_index(["Fields","Question"]).T.stack()

输出

Fields           Post  Pre
       Question           
ChildA Q1           5    3
ChildB Q1           3    2

推荐阅读