基于DataFrame同行多列生成符合条件的性别计数器
基于DataFrame的年龄组匹配性别统计
问题背景
我有一个大型DataFrame,包含多个孩子的具体年龄、性别,以及一些二进制列,示例如下:
kid1_age kid2_age kid3_age kid1_gndr kid2_gndr kid3_gndr .. age_1825 age_1217 .. index 0 18 12 nan Male nan nan 1 1 1 21 17 nan Female Male nan 1 0 2 15 13 1 Female Female Male 0 1
(注:原示例中存在重复列名kid1_gndr,已修正为kid3_gndr保证逻辑合理)
其中age_1825代表年龄在18-25岁的孩子,age_1217代表年龄在12-17岁的孩子,以此类推。二进制列值为1表示对应年龄组的孩子正确填写了数据。
目标是生成Male和Female统计列,统计二进制列值为1且年龄匹配对应组的孩子的性别数量,最终结果示例:
kid1_age kid2_age kid3_age kid1_gndr kid2_gndr kid3_gndr age_1825 age_1217 Male Female 18 12 nan Male nan nan 1 1 2 0 21 17 nan Female Male nan 1 0 0 1 15 13 1 Female Female Male 0 1 0 2
统计逻辑要求:
- 识别正确填写数据的年龄组(二进制列值为1的列)
- 找出年龄落在该组的孩子
- 获取这些孩子的性别
- 累计对应性别的数量
我是Python新手,不知道怎么实现,求帮助。
解决方案
步骤1:定义年龄组与区间的映射
先把所有年龄组列名对应的年龄区间整理成字典,方便后续匹配:
age_group_mapping = { 'age_1825': (18, 25), 'age_1217': (12, 17), # 其他年龄组按此格式补充即可 }
步骤2:筛选孩子的年龄和性别列
从DataFrame中提取所有孩子的年龄列和性别列,确保一一对应:
# 筛选所有以"_age"结尾的列(孩子年龄) age_cols = [col for col in df.columns if col.endswith('_age')] # 筛选所有以"_gndr"结尾的列(孩子性别) gender_cols = [col for col in df.columns if col.endswith('_gndr')]
步骤3:编写逐行统计函数
写一个函数处理DataFrame的每一行,按规则统计符合条件的性别数量:
def count_genders(row): male_count = 0 female_count = 0 # 遍历每个需要统计的年龄组 for group_col, (min_age, max_age) in age_group_mapping.items(): # 仅处理二进制值为1的年龄组 if row[group_col] == 1: # 逐个检查每个孩子的年龄和性别 for age_col, gender_col in zip(age_cols, gender_cols): kid_age = row[age_col] kid_gender = row[gender_col] # 跳过空值数据 if pd.isna(kid_age) or pd.isna(kid_gender): continue # 判断年龄是否在当前组区间内 if min_age <= kid_age <= max_age: # 累计对应性别计数 if kid_gender == 'Male': male_count += 1 elif kid_gender == 'Female': female_count += 1 # 返回统计结果 return pd.Series([male_count, female_count], index=['Male', 'Female'])
步骤4:应用函数生成统计列
将函数应用到原DataFrame的每一行,合并统计结果:
import pandas as pd # 假设你的原始DataFrame名为df stats = df.apply(count_genders, axis=1) # 把统计列合并到原DataFrame result_df = pd.concat([df, stats], axis=1)
完整可运行示例
import pandas as pd # 构造示例数据(修正原重复列名问题) data = { 'kid1_age': [18, 21, 15], 'kid2_age': [12, 17, 13], 'kid3_age': [pd.NA, pd.NA, 1], 'kid1_gndr': ['Male', 'Female', 'Female'], 'kid2_gndr': [pd.NA, 'Male', 'Female'], 'kid3_gndr': [pd.NA, pd.NA, 'Male'], 'age_1825': [1, 1, 0], 'age_1217': [1, 0, 1] } df = pd.DataFrame(data) # 定义年龄组映射 age_group_mapping = { 'age_1825': (18, 25), 'age_1217': (12, 17) } # 筛选年龄和性别列 age_cols = [col for col in df.columns if col.endswith('_age')] gender_cols = [col for col in df.columns if col.endswith('_gndr')] # 统计函数 def count_genders(row): male_count = 0 female_count = 0 for group_col, (min_age, max_age) in age_group_mapping.items(): if row[group_col] == 1: for age_col, gender_col in zip(age_cols, gender_cols): kid_age = row[age_col] kid_gender = row[gender_col] if pd.isna(kid_age) or pd.isna(kid_gender): continue if min_age <= kid_age <= max_age: if kid_gender == 'Male': male_count +=1 elif kid_gender == 'Female': female_count +=1 return pd.Series([male_count, female_count], index=['Male', 'Female']) # 生成统计列并合并 stats = df.apply(count_genders, axis=1) result_df = pd.concat([df, stats], axis=1) # 打印结果 print(result_df)
注意事项
- 若有更多年龄组,只需在
age_group_mapping中补充对应的列名和区间 - 确保孩子的年龄列与性别列严格一一对应(如
kid1_age对应kid1_gndr) - 处理超大型DataFrame时,
apply效率可能偏低,后续可学习向量化操作优化,但此方法对新手更直观易懂
内容的提问来源于stack exchange,提问作者hao
相关产品推荐
相关产品推荐

