如何在Python的Pivot表中循环所有问题?

发布于 2025-02-11 04:10:01 字数 1363 浏览 7 评论 0原文

我正在研究调查,数据看起来像这样:

ID    Q1    Q2    Q3    Gender    Age    Dep    Ethnicity
001   Y      N    Y      F         22     IT        W
002   N      Y    Y      M         35     HR        W
003   Y      N    N      F         20     IT        A
004   Y      N    Y      M         54     OPRE      B
005   Y      N    Y      M         42     OPRE      B

现在,我想添加两个索引dep和性别来创建一个表:

Question  Dep   Response  #M   #F    %M  %F 
     Q1     IT    Y        0    2     0  100
            IT    N        0    0     0   0
            HR    Y        0    0     0   0
            HR    N        1    0     100 0 
            OPRE  Y        2    0     100 0
            OPRE  N        0    0     0   0  
     Q2     IT    Y        0    0     0   0
            IT    N        0    2     0   100
            HR    Y        1    0     100 0
            HR    N        0    0     0   0 
            OPRE  Y        0    0     0   0
            OPRE  N        2    0     100 0
     Q3 ......

我的代码是这样的:

df2=df[['ID','Gender','Dep', 'Q1', 'Q2', 'Q3' ]].melt(
['ID','Gender', 'Dep'],  var_name='question', value_name='response').pivot_table(
index=[ 'question','Dep','response'], 
columns='Gender',
values='ID', aggfunc='count').fillna(0)

如果我有更多问题,我不想复制并粘贴数据框中的所有Q,而是想有一个可以解决所有问题的循环。 谁能帮忙?

I am working on a survey and the data looks like this:

ID    Q1    Q2    Q3    Gender    Age    Dep    Ethnicity
001   Y      N    Y      F         22     IT        W
002   N      Y    Y      M         35     HR        W
003   Y      N    N      F         20     IT        A
004   Y      N    Y      M         54     OPRE      B
005   Y      N    Y      M         42     OPRE      B

Now, I'd like to add two indexes Dep and Gender to create a table like:

Question  Dep   Response  #M   #F    %M  %F 
     Q1     IT    Y        0    2     0  100
            IT    N        0    0     0   0
            HR    Y        0    0     0   0
            HR    N        1    0     100 0 
            OPRE  Y        2    0     100 0
            OPRE  N        0    0     0   0  
     Q2     IT    Y        0    0     0   0
            IT    N        0    2     0   100
            HR    Y        1    0     100 0
            HR    N        0    0     0   0 
            OPRE  Y        0    0     0   0
            OPRE  N        2    0     100 0
     Q3 ......

My codes are like this:

df2=df[['ID','Gender','Dep', 'Q1', 'Q2', 'Q3' ]].melt(
['ID','Gender', 'Dep'],  var_name='question', value_name='response').pivot_table(
index=[ 'question','Dep','response'], 
columns='Gender',
values='ID', aggfunc='count').fillna(0)

If I have more questions, I don't want to copy and paste all the Qs in the dataframe, instead I'd like to have a loop which can go over all the questions.
Can anyone help?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

心是晴朗的。 2025-02-18 04:10:01

iiuc,您可以使用pd.wide_to_long

out = (pd.wide_to_long(df, stubnames='Q', i=['ID', 'Dep', 'Ethnicity'], j='Question')
         .reset_index().rename(columns={'Q': 'Response'}).assign(Count=1)
         .pivot_table('Count', ['Question', 'Dep', 'Response'], 'Gender', 
                      fill_value=0, aggfunc='count'))

输出:

>>> out
Gender                  F  M
Question Dep  Response      
1        HR   N         0  1
         IT   Y         2  0
         OPRE Y         0  2
2        HR   Y         0  1
         IT   N         2  0
         OPRE N         0  2
3        HR   Y         0  1
         IT   N         1  0
              Y         1  0
         OPRE Y         0  2

IIUC, you can use pd.wide_to_long:

out = (pd.wide_to_long(df, stubnames='Q', i=['ID', 'Dep', 'Ethnicity'], j='Question')
         .reset_index().rename(columns={'Q': 'Response'}).assign(Count=1)
         .pivot_table('Count', ['Question', 'Dep', 'Response'], 'Gender', 
                      fill_value=0, aggfunc='count'))

Output:

>>> out
Gender                  F  M
Question Dep  Response      
1        HR   N         0  1
         IT   Y         2  0
         OPRE Y         0  2
2        HR   Y         0  1
         IT   N         2  0
         OPRE N         0  2
3        HR   Y         0  1
         IT   N         1  0
              Y         1  0
         OPRE Y         0  2
何以心动 2025-02-18 04:10:01

这是一种通过按照您进行的融化,将响应转换为pd.categorical,然后将

import pandas as pd

df = pd.DataFrame({
    'ID': [1, 2, 3, 4, 5],
    'Q1': ['Y', 'N', 'Y', 'Y', 'Y'],
    'Q2': ['N', 'Y', 'N', 'N', 'N'],
    'Q3': ['Y', 'Y', 'N', 'Y', 'Y'],
    'Gender': ['F', 'M', 'F', 'M', 'M'],
    'Age': [22, 35, 20, 54, 42],
    'Dep': ['IT', 'HR', 'IT', 'OPRE', 'OPRE'],
    'Ethnicity': ['W', 'W', 'A', 'B', 'B'],
})

#melt to long form
long_df = df.melt(
    id_vars=['ID','Gender','Age','Dep','Ethnicity'],
    var_name='Question',
    value_name='Response',
)

#convert Gender/Response to categorical to keep 0's
long_df['Response'] = pd.Categorical(long_df['Response'])

#groupby Q/Dep/Response and agg to get M/F/Frac_M/Frac_F
agg_df = long_df.groupby(['Question','Dep','Response']).agg(
    M = ('Gender', lambda g: g.eq('M').sum()),
    F = ('Gender', lambda g: g.eq('F').sum()),
    Frac_M = ('Gender', lambda g: g.eq('M').sum()/len(g)*100),
    Frac_F = ('Gender', lambda g: g.eq('F').sum()/len(g)*100),
).fillna(0)

print(agg_df)

”

Here's a way to keep the 0 rows by melting to long form as you're doing, converting the Response to a pd.Categorical, and then groupbing and aggregating

import pandas as pd

df = pd.DataFrame({
    'ID': [1, 2, 3, 4, 5],
    'Q1': ['Y', 'N', 'Y', 'Y', 'Y'],
    'Q2': ['N', 'Y', 'N', 'N', 'N'],
    'Q3': ['Y', 'Y', 'N', 'Y', 'Y'],
    'Gender': ['F', 'M', 'F', 'M', 'M'],
    'Age': [22, 35, 20, 54, 42],
    'Dep': ['IT', 'HR', 'IT', 'OPRE', 'OPRE'],
    'Ethnicity': ['W', 'W', 'A', 'B', 'B'],
})

#melt to long form
long_df = df.melt(
    id_vars=['ID','Gender','Age','Dep','Ethnicity'],
    var_name='Question',
    value_name='Response',
)

#convert Gender/Response to categorical to keep 0's
long_df['Response'] = pd.Categorical(long_df['Response'])

#groupby Q/Dep/Response and agg to get M/F/Frac_M/Frac_F
agg_df = long_df.groupby(['Question','Dep','Response']).agg(
    M = ('Gender', lambda g: g.eq('M').sum()),
    F = ('Gender', lambda g: g.eq('F').sum()),
    Frac_M = ('Gender', lambda g: g.eq('M').sum()/len(g)*100),
    Frac_F = ('Gender', lambda g: g.eq('F').sum()/len(g)*100),
).fillna(0)

print(agg_df)

enter image description here

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文