Python 如何将具有1级索引层次结构的数据帧转换为3级索引层次结构

Python 如何将具有1级索引层次结构的数据帧转换为3级索引层次结构,python,pandas,dataframe,Python,Pandas,Dataframe,我有一个平面数据框,如下所示: 我想把它转换成这样的数据帧: 对于每个版本(版本)的每个测试(T),我想将在给定likert量表上绘制的答案计数(为了演示,我将其减少到3个条目)汇总为百分比 每种T和版本组合的整套利克特标度值总和应为100% likert = { 'Agree': 1, 'Undecided': 2, 'Disagree': 3, } 这怎么可能? 谢谢你的帮助 可能不是最优雅的解决方案,但我认为这实现了您的目标。假设您的数据帧名为df(我在两个刻

我有一个平面数据框,如下所示:

我想把它转换成这样的数据帧:

对于每个版本(版本)的每个测试(T),我想将在给定likert量表上绘制的答案计数(为了演示,我将其减少到3个条目)汇总为百分比

每种T和版本组合的整套利克特标度值总和应为100%

likert = {
    'Agree': 1,
    'Undecided': 2,
    'Disagree': 3,
}
这怎么可能?
谢谢你的帮助

可能不是最优雅的解决方案,但我认为这实现了您的目标。假设您的数据帧名为
df
(我在两个刻度之间随机取样,因此我的
df
与您描述的不完全相同):

这会将数据帧转换为长格式:

#     T Version variable      Scale
# 0   1       A       Q1  Undecided
# 1   1       A       Q1   Disagree
# 2   1       A       Q1  Undecided
# 3   1       A       Q1      Agree
然后,您需要计算每个变量组合的大小,可以通过以下方式完成:

res = res.groupby(['T', 'Version', 'Scale', 'variable']).size()
这将产生:

# T  Version  Scale      variable
# 1  A        Agree      Q1          2
#                        Q2          1
#             Disagree   Q2          3
#             Undecided  Q1          2
#    B        Agree      Q1          1
然后,要将
Q1
Q2
移动到列中,请按如下方式取消堆叠最后一个索引级别:

res = res.unstack(level=-1).fillna(0)

# variable              Q1   Q2
# T Version Scale
# 1 A       Agree      2.0  1.0
#           Disagree   0.0  3.0
#           Undecided  2.0  0.0
最后,要计算前两个指数级别的每个组合的百分比:

res = res.groupby(level=[0, 1]).apply(lambda x: 100. * x / x.sum())
这将产生所需的结果:

# variable                     Q1         Q2
# T Version Scale
# 1 A       Agree       50.000000  25.000000
#           Disagree     0.000000  75.000000
#           Undecided   50.000000   0.000000
#   B       Agree       33.333333   0.000000
#           Disagree    66.666667  66.666667

可能不是最优雅的解决方案,但我认为这实现了您的目标。假设您的数据帧名为
df
(我在两个刻度之间随机取样,因此我的
df
与您描述的不完全相同):

这会将数据帧转换为长格式:

#     T Version variable      Scale
# 0   1       A       Q1  Undecided
# 1   1       A       Q1   Disagree
# 2   1       A       Q1  Undecided
# 3   1       A       Q1      Agree
然后,您需要计算每个变量组合的大小,可以通过以下方式完成:

res = res.groupby(['T', 'Version', 'Scale', 'variable']).size()
这将产生:

# T  Version  Scale      variable
# 1  A        Agree      Q1          2
#                        Q2          1
#             Disagree   Q2          3
#             Undecided  Q1          2
#    B        Agree      Q1          1
然后,要将
Q1
Q2
移动到列中,请按如下方式取消堆叠最后一个索引级别:

res = res.unstack(level=-1).fillna(0)

# variable              Q1   Q2
# T Version Scale
# 1 A       Agree      2.0  1.0
#           Disagree   0.0  3.0
#           Undecided  2.0  0.0
最后,要计算前两个指数级别的每个组合的百分比:

res = res.groupby(level=[0, 1]).apply(lambda x: 100. * x / x.sum())
这将产生所需的结果:

# variable                     Q1         Q2
# T Version Scale
# 1 A       Agree       50.000000  25.000000
#           Disagree     0.000000  75.000000
#           Undecided   50.000000   0.000000
#   B       Agree       33.333333   0.000000
#           Disagree    66.666667  66.666667

groupby.apply(lambda x:100.*x/x.sum())
100.*res/res.groupby.transform('sum')
?感谢您的快速回复-不幸的是,我在应用
res=df.groupby(['T','Version','Scale','variable']).size()时出错
KeyError:“Scale”
我做错了什么?@我认为这不可行,因为索引(res有一个三级索引,聚合有两个)。@Hmmm它被支持为
res=res.groupby
~。这是我的错,我已经修复了答案。通过转换,您可以得到原始索引。Is
groupby.apply(lambda x:100.*x/x.sum())
100.*res/res.groupby.transform('sum')
?感谢您的快速回复-不幸的是,我在应用
res=df.groupby(['T','Version','Scale','variable']).size()时出错
KeyError:“Scale”
我做错了什么?@我认为这不可行,因为索引(res有一个三级索引,聚合有两个)。@Hmmm它被支持为
res=res.groupby
~。这是我的错,我已经修正了答案。通过转换你可以得到原始索引。