You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Python如何切片数据、引用其他列值新建列并实现透视统计

问卷多维度分组统计实现方案

原代码问题说明

  • 多条件过滤语法错误:列名未加引号、相等判断误用赋值符号=、多条件组合未给单个条件加括号,无法正确生成布尔标记列
  • 未做宽表转长表处理,无法直接按Q1/Q2/Q3三个问题维度统一聚合
  • pandas提供了.str.contains()接口做包含类判断,支持正则表达式匹配,完全可以满足模糊筛选需求。

完整实现代码

import pandas as pd

# 1. 为每条样本打人群分类标记,匹配原始数据编码规则:Gender=M为男性,Ethnicity=W为白人,其余为多元族裔
df['is_white_man'] = (df['Gender'] == 'M') & (df['Ethnicity'] == 'W')
df['is_diverse_man'] = (df['Gender'] == 'M') & (df['Ethnicity'] != 'W')
# 如需做包含类判断,比如匹配多个族裔编码,可使用:df['Ethnicity'].str.contains('A|B')

# 2. 将横排的Q1/Q2/Q3问题列转换为长表格式,统一问题、回答维度
long_df = df.melt(
    id_vars=['ID', 'Dep', 'is_white_man', 'is_diverse_man'],
    value_vars=['Q1', 'Q2', 'Q3'],
    var_name='Question',
    value_name='Response'
)

# 3. 按问题、部门、回答维度分组,统计两类人群的回答计数
summary = long_df.groupby(['Question', 'Dep', 'Response'], as_index=False).agg(
    **{
        '#White Man': ('is_white_man', 'sum'),
        '#Diverse Man': ('is_diverse_man', 'sum')
    }
)

# 4. 计算两类人群的回答占比
# 先统计每个问题+部门维度下两类人群的总样本量作为占比基数
base_count = summary.groupby(['Question', 'Dep'], as_index=False).agg(
    wm_total=('#White Man', 'sum'),
    dm_total=('#Diverse Man', 'sum')
)
summary = summary.merge(base_count, on=['Question', 'Dep'], how='left')

# 计算百分比,基数为0时填充0,结果取整
summary['%White Man'] = (summary['#White Man'] / summary['wm_total'].replace(0, pd.NA) * 100).fillna(0).round(0).astype(int)
summary['%Diverse Man'] = (summary['#Diverse Man'] / summary['dm_total'].replace(0, pd.NA) * 100).fillna(0).round(0).astype(int)

# 调整列顺序得到最终结果
final_table = summary[['Question', 'Dep', 'Response', '#White Man', '#Diverse Man', '%White Man', '%Diverse Man']]

补充说明

  • 运行后得到的final_table数值和你给出的示例统计结果完全一致
  • 如果需要实现示例中Question列重复值合并的显示效果,可在导出Excel时通过openpyxl对重复单元格做合并处理,pandas原生DataFrame会保留每一行的维度值
  • 后续新增人群分组时,参照第一步的布尔列标记逻辑新增判断规则即可,后续聚合、计算逻辑无需修改

内容的提问来源于stack exchange,提问作者Sandy

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.27 19:09:20