通过门店销售明细表用Python Pandas得到每月每个门店的销冠和按月的同比环比数据
假设我在本地有Excel销售表,包含ID主键、门店ID、日期、销售员姓名和销售额,需要用Pandas统计出每个月所有门店和各门店销售额最高的人,不一定是一个人,以及他所在的门店ID和月总销售额。
步骤1:导入数据并处理日期
import pandas as pd# 读取Excel文件
df = pd.read_excel('sales.xlsx')# 转换日期格式并提取月份
df['日期'] = pd.to_datetime(df['日期'])
df['月份'] = df['日期'].dt.to_period('M') # 或使用.strftime('%Y-%m')
步骤2:统计各门店每月销售额最高的销售员
# 按月份、门店、销售员分组求和
store_monthly_sales = df.groupby(['月份', '门店ID', '销售员姓名'])['销售额'].sum().reset_index()# 找出每个门店每月的最高销售额
store_monthly_sales['max_sales'] = store_monthly_sales.groupby(['月份', '门店ID'])['销售额'].transform('max')
highest_per_store = store_monthly_sales[store_monthly_sales['销售额'] == store_monthly_sales['max_sales']].drop(columns='max_sales')
步骤3:统计所有门店每月销售额最高的销售员
# 按月份和销售员分组求和,并合并门店ID
all_store_sales = df.groupby(['月份', '销售员姓名']).agg(总销售额=('销售额', 'sum'),门店ID=('门店ID', lambda x: ', '.join(map(str, x.unique())))
).reset_index()# 找出每月最高总销售额
all_store_sales['max_total'] = all_store_sales.groupby('月份')['总销售额'].transform('max')
highest_all_stores = all_store_sales[all_store_sales['总销售额'] == all_store_sales['max_total']].drop(columns='max_total')
步骤4:导出结果到Excel
with pd.ExcelWriter('result.xlsx') as writer:highest_per_store.to_excel(writer, sheet_name='各门店月度冠军', index=False)highest_all_stores.to_excel(writer, sheet_name='全公司月度冠军', index=False)
结果说明
- 各门店月度冠军:包含月份、门店ID、销售员姓名及其销售额,可能有多个销售员并列。
- 全公司月度冠军:包含月份、销售员姓名、总销售额及其涉及的所有门店ID,可能有多个销售员并列。
假设我在本地有Excel销售表,包含ID主键、门店ID、日期、销售员姓名和销售额,需要用Pandas统计出按月统计的同比和环比数据,当前月如果不是月底的话,同比或环比数据需要取得上个月或者去年1日到对应的日期的总销售额值。
import pandas as pdfrom pandas.tseries.offsets import DateOffsetdef calculate_yoy_mom_sales(file_path, current_date=None):# 读取数据并处理日期df = pd.read_excel(file_path)df['日期'] = pd.to_datetime(df['日期'])# 设置当前日期(默认为数据最新日期)current_date = pd.to_datetime(current_date) if current_date else df['日期'].max()# 生成日期范围辅助列df['年月'] = df['日期'].dt.to_period('M')# 计算所有可能的月份范围min_date = df['日期'].min()max_date = current_datefull_months = pd.period_range(start=min_date, end=max_date, freq='M')results = []for period in full_months:# 当前统计月份信息month_start = period.start_timemonth_end = min(period.end_time, current_date)# 当前时间段销售额current_mask = (df['日期'] >= month_start) & (df['日期'] <= month_end)current_sales = df[current_mask]['销售额'].sum()# 同比计算(去年同时间段)last_year_start = month_start - DateOffset(years=1)last_year_end = month_end - DateOffset(years=1)last_year_mask = (df['日期'] >= last_year_start) & (df['日期'] <= last_year_end)yoy_sales = df[last_year_mask]['销售额'].sum()# 环比计算(上月同时间段)last_month_start = month_start - DateOffset(months=1)last_month_end = month_end - DateOffset(months=1)# 确保环比结束日期不超过上月最后一天last_month_end = min(last_month_end, last_month_start + pd.offsets.MonthEnd(1))mom_mask = (df['日期'] >= last_month_start) & (df['日期'] <= last_month_end)mom_sales = df[mom_mask]['销售额'].sum()results.append({'统计月份': period.strftime('%Y-%m'),'开始日期': month_start.date(),'结束日期': month_end.date(),'当月销售额': current_sales,'同比销售额': yoy_sales,'环比销售额': mom_sales,'同比增幅': (current_sales - yoy_sales) / yoy_sales if yoy_sales != 0 else None,'环比增幅': (current_sales - mom_sales) / mom_sales if mom_sales != 0 else None})result_df = pd.DataFrame(results)return result_df# 使用示例
result = calculate_yoy_mom_sales('sales.xlsx', '2023-06-15')
print(result)
方案特点:
-
动态日期处理:
- 自动处理非完整月份(如当前月到15号)
- 智能对齐同比/环比时间段(自动调整到相同天数)
- 处理月份天数差异(如2月28日对比)
-
输出结果包含:
- 统计月份
- 实际统计日期范围
- 当月销售额
- 同比销售额(去年同期相同天数)
- 环比销售额(上月同期相同天数)
- 同比/环比增长率
-
使用方式:
# 自动使用数据最新日期 result = calculate_yoy_mom_sales('sales.xlsx') # 指定截止日期 result = calculate_yoy_mom_sales('sales.xlsx', '2023-06-15')
-
处理边界情况:
- 当月天数 > 比较月份天数时自动截断到月末
- 处理零销售额时的增长率计算
- 自动生成完整的时间序列(包含无销售的月份)
输出示例:
统计月份 | 开始日期 | 结束日期 | 当月销售额 | 同比销售额 | 环比销售额 | 同比增幅 | 环比增幅 |
---|---|---|---|---|---|---|---|
2023-06 | 2023-06-01 | 2023-06-15 | 150000 | 120000 | 140000 | 0.25 | 0.071 |
2023-05 | 2023-05-01 | 2023-05-31 | 300000 | 280000 | 250000 | 0.071 | 0.2 |
注意事项:
- 保证日期字段的完整性,缺失日期会导致统计偏差
- 无历史数据时增长率显示为None
- 建议配合数据验证使用(如检查日期范围是否合理)
- 结果包含所有自然月,即使当月没有销售数据