使用Pandas按类别计算日期间数值差值的最优实现探讨
更简洁高效的Pandas实现:按类别计算2011-2020年数值增幅极值
需求说明
需要在Pandas DataFrame中按日期(年份)和类别(Borough)分组计算数值总和的差值,最终获取2011年与2020年之间数值增幅最小和最大的类别名称及对应增幅。现有代码可实现需求,但存在重复操作、逻辑分散的问题,以下是更优的实现方案。
优化方案一:使用透视表(pivot_table)
这种方式直观清晰,能同时展示各年份的分组总和,便于后续扩展分析:
import pandas as pd import numpy as np # 生成随机测试数据 size = 1_000 df = pd.DataFrame({ 'Borough': np.random.choice(['Brooklyn', 'Manhattan', 'Bronx', 'Queens', 'Staten Island'], size), 'Date': pd.to_datetime(np.random.randint(2011, 2021, size), format="%Y"), 'Nbr_permits': np.random.randint(0, 300, size) }) # 1. 仅筛选目标年份数据,提取年份列 filtered_df = df[df['Date'].dt.year.isin([2011, 2020])].copy() filtered_df['Year'] = filtered_df['Date'].dt.year # 2. 生成透视表:按区域分组,列展示年份,值为许可数量总和 pivot = filtered_df.pivot_table(index='Borough', columns='Year', values='Nbr_permits', aggfunc='sum') # 3. 计算2020-2011的增幅,剔除缺失数据(某年份无记录的区域) growth = (pivot[2020] - pivot[2011]).dropna().sort_values() # 4. 获取增幅极值 min_borough, min_growth = growth.idxmin(), growth.min() max_borough, max_growth = growth.idxmax(), growth.max() print(f"增幅最小的区域:{min_borough},增幅值:{min_growth}") print(f"增幅最大的区域:{max_borough},增幅值:{max_growth}")
优势
- 仅过滤一次数据,避免原代码中两次重复的年份筛选与分组操作,提升运行效率
- 透视表结构直观,可直接查看各区域的年度总和,便于调试和扩展分析
- 计算逻辑集中,代码可读性更强
优化方案二:链式调用(groupby + unstack)
这种写法更紧凑,符合Pandas的惯用风格,适合追求代码简洁的场景:
import pandas as pd import numpy as np # 生成随机测试数据 size = 1_000 df = pd.DataFrame({ 'Borough': np.random.choice(['Brooklyn', 'Manhattan', 'Bronx', 'Queens', 'Staten Island'], size), 'Date': pd.to_datetime(np.random.randint(2011, 2021, size), format="%Y"), 'Nbr_permits': np.random.randint(0, 300, size) }) # 链式完成筛选、分组、转置、差值计算 growth = (df[df['Date'].dt.year.isin([2011, 2020])] .assign(Year=lambda x: x['Date'].dt.year) .groupby(['Borough', 'Year'])['Nbr_permits'].sum() .unstack('Year') .pipe(lambda x: x[2020] - x[2011]) .dropna() .sort_values()) # 获取并输出极值结果 print(f"增幅最小:{growth.idxmin()},数值:{growth.min()}") print(f"增幅最大:{growth.idxmax()},数值:{growth.max()}")
优势
- 全程链式调用,代码简洁紧凑,无需中间变量
- 使用
assign和pipe方法简化步骤,保持逻辑连贯性 - 同样避免了重复计算,运行效率与方案一相当
内容的提问来源于stack exchange,提问作者Lucien S.
相关产品推荐
相关产品推荐

