Возможно, это не самое элегантное решение, но я думаю, что оно достигает вашей цели.Предположим, ваш фрейм данных называется df
(я случайно выбрал шкалу, поэтому мой df
не совсем то, что вы описали):
res = df.melt(id_vars=['T', 'Version'], value_vars=['Q1', 'Q2'], value_name='Scale')
Это преобразует ваш фрейм данных в длинный формат:
# 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