如何在Python Pandas中简化多查询分组以生成指定统计表格?
问题
需要生成按SEMESTRE分组,统计各学期下CACHIMBOS、REGULAR、EGRESANTE数量的表格,预期格式如下:
| SEMESTRE | Number of 'CACHIMBOS' | Number of 'REGULAR' | Number of 'EGRESANTE' |
|---|---|---|---|
| 2019-I | 0 | X | X |
| 2019-II | X | x | x |
| 2020-I | |||
| 2020-II | |||
| 2021-I | |||
| 2021-II | 41 | 453 | 40 |
已提取数据最后两列得到df9:
df9 = df.iloc[:, [11,12]] df9
df9示例数据:
Condicion Semestre 0 REGULAR 2019-I 1 REGULAR 2019-I 2 REGULAR 2019-I 5 EGRESANTE 2019-I 8 REGULAR 2019-I ... ... ... 3008 REGULAR 2021-II 3009 REGULAR 2021-II 3010 REGULAR 2021-II 3011 REGULAR 2021-II 3012 REGULAR 2021-II
尝试了以下代码,仅得到2021-II学期的统计结果:
options = ['CACHIMBO', 'REGULAR', 'EGRESANTE'] new_df = df9[df9['Condicion'].isin(options)] new_df raa = new_df.groupby(['Condicion', df9.iloc[:,1] == '2021-II'] ).size().reset_index(name='Total') raa raa1 = raa.loc[raa['Semestre'] == True] raa1 tabla1 = raa1.loc[:, raa1.columns != 'Semestre'] tabla1
结果:
Condicion Total 0 CACHIMBO 41 2 EGRESANTE 40 4 REGULAR 453
请问是否有简化代码的方法?通过合并DataFrame实现预期结果是否可行?
简化方案
一、一步到位生成目标表格
直接用pandas内置的crosstab或pivot_table函数,两行核心代码就能生成符合预期的统计表格,无需分步筛选分组:
方法1:使用pd.crosstab
import pandas as pd options = ['CACHIMBO', 'REGULAR', 'EGRESANTE'] # 筛选目标类别后生成交叉表,自动按学期分组统计 result = pd.crosstab( df9[df9['Condicion'].isin(options)]['Semestre'], df9[df9['Condicion'].isin(options)]['Condicion'], dropna=False ).fillna(0).astype(int) # 重命名列名匹配预期格式 result.columns = [f"Number of '{col}'" for col in result.columns] # 重置索引将Semestre转为普通列 result = result.reset_index().rename(columns={'Semestre': 'SEMESTRE'})
方法2:使用pivot_table
import pandas as pd options = ['CACHIMBO', 'REGULAR', 'EGRESANTE'] filtered_df = df9[df9['Condicion'].isin(options)] # 按学期和类别透视统计,缺失值填充0 result = filtered_df.pivot_table( index='Semestre', columns='Condicion', aggfunc='size', fill_value=0 ).reset_index() # 调整列名格式 result.columns = ['SEMESTRE'] + [f"Number of '{col}'" for col in result.columns[1:]]
两种方法都会生成包含所有学期的完整统计表格,缺失的类别会自动填充0,完全匹配预期格式。
二、合并DataFrame的可行性
合并DataFrame是可行的,但属于冗余方案——需要先按每个Condicion单独分组统计,再把多个结果按SEMESTRE合并,代码量远多于上述方法:
import pandas as pd options = ['CACHIMBO', 'REGULAR', 'EGRESANTE'] dfs = [] for cond in options: # 按学期统计单个类别的数量 temp = df9[df9['Condicion'] == cond].groupby('Semestre').size().reset_index(name=f"Number of '{cond}'") dfs.append(temp) # 依次合并所有统计结果 result = dfs[0] for df in dfs[1:]: result = pd.merge(result, df, on='Semestre', how='outer').fillna(0).astype(int)
这种方法逻辑繁琐,效率更低,因此更推荐直接使用crosstab或pivot_table。
内容的提问来源于stack exchange,提问作者SchneiderJinn
相关产品推荐
相关产品推荐

