29 农产品交易销售趋势与产品结构分析
29.1 引言深度分析目标
- 销售趋势分析: 时间规律、季节性、周期性
- 产品结构分析: 市场格局、价格段、季节性差异
29.2 销售趋势分析
# 注:processed_data.csv数据文件本地没有,但平台已经内置
from datetime import datetime, timedelta
from matplotlib.dates import MonthLocator, DateFormatter # 导入Matplotlib库
from sklearn.linear_model import LinearRegression # 导入Scikit-learn的LinearRegression模块
def sales_trend_analysis(orders): # 销售趋势分析函数
data['下单日期'] = pd.to_datetime(data['order_date']).dt.date # 转换为日期格式
# 按日期统计订单数和销售额
daily_sales = data.groupby('下单日期').agg({'order_id':'count','sales_amount':'sum'}).reset_index()
daily_sales.columns = ['日期', '订单数', '销售额'] # 重命名列
# 计算7日移动平均线(平滑波动)
daily_sales['订单数_7日均值'] = daily_sales['订单数'].rolling(window=7, min_periods=1).mean()
daily_sales['销售额_7日均值'] = daily_sales['销售额'].rolling(window=7, min_periods=1).mean() # 设置滚动窗口计算
# 可视化每日销售数据
fig, (ax1, ax2) = plt.subplots(2, 1, figsize=(18, 14), sharex=True)
# 订单数趋势图
ax1.plot(daily_sales['日期'], daily_sales['订单数'], 'b-', alpha=0.3, label='每日订单数')
ax1.plot(daily_sales['日期'], daily_sales['订单数_7日均值'], 'r-', label='7日移动平均') # 在子图上绑制曲线
ax1.set_title('每日订单量趋势') # 设置图表标题
ax1.set_ylabel('订单数量') # 设置Y轴标签
ax1.legend() # 设置图例
ax1.grid(True) # 设置网格线
# 销售额趋势图
ax2.plot(daily_sales['日期'], daily_sales['销售额'], 'g-', alpha=0.3, label='每日销售额')
ax2.plot(daily_sales['日期'], daily_sales['销售额_7日均值'], 'r-', label='7日移动平均') # 在子图上绑制曲线
ax2.set_title('每日销售额趋势') # 设置图表标题
ax2.set_xlabel('日期') # 设置X轴标签
ax2.set_ylabel('销售额(元)') # 设置Y轴标签
ax2.legend() # 设置图例
ax2.grid(True) # 设置网格线
# 设置日期显示格式
ax2.xaxis.set_major_locator(MonthLocator())
ax2.xaxis.set_major_formatter(DateFormatter('%Y-%m')) # 配置子图属性
plt.tight_layout() # 自动调整布局防止重叠
plt.savefig("每日销售趋势.png") # 保存图表
# 月度销售趋势分析
data['年月'] = pd.to_datetime(data['order_date']).dt.strftime('%Y-%m') # 提取年月
# 按月统计订单数和销售额
monthly_sales = data.groupby('年月').agg({'order_id':'count','sales_amount':'sum'}).reset_index()
monthly_sales.columns = ['年月', '订单数', '销售额'] # 重命名列
# 可视化月度销售数据
fig, (ax1, ax2) = plt.subplots(2, 1, figsize=(16, 12))
# 月度订单数柱状图
ax1.bar(monthly_sales['年月'], monthly_sales['订单数'], color='skyblue')
ax1.set_title('月度订单数') # 设置图表标题
ax1.set_ylabel('订单数量') # 设置Y轴标签
# 设置X轴刻度标签水平显示(旋转角度为0度)
plt.setp(ax1.xaxis.get_majorticklabels(), rotation=0)
ax1.grid(axis='y') # 设置网格线
for i, v in enumerate(monthly_sales['订单数']): # 添加数值标签
ax1.text(i, v + 10, str(v), ha='center', va='bottom', fontsize=10) # 配置子图属性
# 月度销售额柱状图
ax2.bar(monthly_sales['年月'], monthly_sales['销售额'], color='lightgreen')
ax2.set_title('月度销售额') # 设置图表标题
ax2.set_xlabel('年月') # 设置X轴标签
ax2.set_ylabel('销售额(元)') # 设置Y轴标签
# 设置X轴刻度标签水平显示(旋转角度为0度)
plt.setp(ax2.xaxis.get_majorticklabels(), rotation=0)
ax2.grid(axis='y') # 设置网格线
for i, v in enumerate(monthly_sales['销售额']): # 添加数值标签
ax2.text(i, v + 1000, f"{v:.2f}", ha='center', va='bottom', fontsize=10) # 配置子图属性
plt.tight_layout() # 自动调整布局防止重叠
plt.savefig("月度销售数据.png") # 保存图表
# 季度商品大类销售额分析
data['order_date'] = pd.to_datetime(data['order_date']) # 转换日期格式
data['年季'] = data['order_date'].dt.year.astype(str) + '-Q' + data['order_date'].dt.quarter.astype(str) # 提取年季
# 按年季和产品类型统计销售额
quarterly_category_sales = data.groupby(['年季', 'category'])['sales_amount'].sum().reset_index()
# 转换为透视表便于绘图
quarterly_pivot = quarterly_category_sales.pivot(index='年季', columns='category', values='sales_amount').fillna(0)
# 可视化季度商品销售额
ax = quarterly_pivot.plot(kind='bar', stacked=True, figsize=(16,10), colormap='viridis')
ax.set_title('季度各品类销售额', fontsize=16) # 设置图表标题
ax.set_xlabel('年-季度', fontsize=14) # 设置X轴标签
ax.set_ylabel('销售额(元)', fontsize=14) # 设置Y轴标签
ax.legend(title='商品大类', bbox_to_anchor=(1.05, 1), loc='upper left') # 设置图例
plt.xticks(rotation=0) # 设置X轴刻度标签
ax.grid(axis='y') # 设置网格线
plt.tight_layout() # 自动调整布局防止重叠
plt.savefig("季度品类销售额.png") # 保存图表
# 销售额预测(简单线性趋势)
daily_sales['日期_数值'] = (pd.to_datetime(daily_sales['日期']) - pd.to_datetime(daily_sales['日期'].min())).dt.days # 日期转数值
# 准备特征和目标变量
X = daily_sales[['日期_数值']]
y_orders = daily_sales['订单数'] # 提取订单数列作为y_orders变量
y_sales = daily_sales['销售额'] # 提取销售额列作为y_sales变量
# 训练线性回归模型
model_orders = LinearRegression()
model_sales = LinearRegression() # 初始化线性回归模型
model_orders.fit(X, y_orders) # 在数据上训练model_orders模型
model_sales.fit(X, y_sales) # 在数据上训练model_sales模型
# 预测未来30天
last_date = pd.to_datetime(daily_sales['日期'].max())
future_dates = [last_date + timedelta(days=i) for i in range(1, 31)] # 生成未来日期
future_df = pd.DataFrame({'日期': future_dates}) # 创建数据框future_df
future_df['日期_数值'] = (pd.to_datetime(future_df['日期']) - pd.to_datetime(daily_sales['日期'].min())).dt.days # 未来日期转数值
# 预测订单数和销售额
future_df['订单数预测'] = model_orders.predict(future_df[['日期_数值']])
future_df['销售额预测'] = model_sales.predict(future_df[['日期_数值']]) # 使用模型进行预测
# 显示预测结果
print("未来30天销售预测:")
print((future_df.head(10))) # 输出前几行数据
# 可视化预测结果
plt.figure(figsize=(18, 10))
plt.plot(pd.to_datetime(daily_sales['日期']), daily_sales['销售额'], 'b-', alpha=0.5, label='历史销售额') # 历史数据
plt.plot(future_df['日期'], future_df['销售额预测'], 'r--', label='销售额预测') # 预测数据
plt.axvspan(last_date, future_df['日期'].max(), alpha=0.2, color='gray') # 标记预测区间
plt.title('销售额趋势与预测') # 设置图表标题
plt.xlabel('日期') # 设置X轴标签
plt.ylabel('销售额(元)') # 设置Y轴标签
plt.legend() # 添加图例
plt.grid(True) # 显示网格线
plt.tight_layout() # 自动调整布局防止重叠
plt.savefig("销售额预测.png") # 保存图表
print("销售趋势分析完成") # 输出销售趋势分析完成
# 进行销售趋势分析
sales_trend_analysis(data)平台任务解答代码
以下代码与教学平台任务要求完全一致:
# 注:processed_data.csv数据文件本地没有,但平台已经内置;squarify包本地未安装,但平台已经内置
# ⚠️ 平台原始代码 - 请原样输入至教学平台(注释除外),平台才会判定答案正确
import pandas as pd # 导入Pandas数据分析库
import numpy as np # 导入NumPy数值计算库
import matplotlib.pyplot as plt # 导入Matplotlib绑图库
import seaborn as sns # 导入Seaborn可视化库
import warnings # 导入warnings模块用于控制警告输出
warnings.filterwarnings('ignore') # 忽略警告
plt.rcParams['font.sans-serif'] = ['SimHei'] # 中文显示
plt.rcParams['axes.unicode_minus'] = False # 负号显示
data = pd.read_csv('processed_data.csv') # 读取数据
# 产品分类映射
category_mapping = {'安溪铁观音':'茶叶','武夷岩茶':'茶叶','福州茉莉花':'茶叶','古田银耳':'食用菌','建宁莲子':'中药材','琯溪蜜柚':'水果','宁德大黄鱼':'水产品'}
data['category'] = data['product_name'].map(category_mapping).fillna(data['category']) # 更新产品分类
print(data.head()) # 查看数据
# 产品分析
import squarify # 导入树形图库
# 创建季节特征(复用之前的季节映射)
seasons = {1: '冬季', 2: '冬季', 3: '春季', 4: '春季', 5: '春季', 6: '夏季', 7: '夏季', 8: '夏季', 9: '秋季', 10: '秋季', 11: '秋季', 12: '冬季'}
data['下单月份'] = pd.to_datetime(data['order_date']).dt.month # 提取月份
data['order_season'] = data['下单月份'].map(seasons) # 映射季节
def product_analysis(orders): # 产品分析函数
# 按商品大类统计销售数据
category_stats = data.groupby('category').agg({'order_id':'count','sales_amount':'sum'}).reset_index() #【要求1】
category_stats.columns = ['产品类型', '订单数', '销售额'] # 重命名列
category_stats['平均订单金额'] = category_stats['销售额'] / category_stats['订单数'] # 计算平均订单金额
category_stats = category_stats.sort_values('销售额', ascending=False) # 按销售额排序
# 显示商品大类统计
print("产品类型统计:")
print(category_stats) # 输出统计量数据
# 可视化商品大类销售额
plt.figure(figsize=(14, 8))
sns.barplot(x='产品类型', y='销售额', data=category_stats, palette='viridis') # 绑制分类柱状图
plt.title('各商品大类销售额') # 设置图表标题
plt.xlabel('产品类型') # 设置X轴标签
plt.ylabel('销售额(元)') # 设置Y轴标签
plt.grid(axis='y') # 显示网格线
plt.tight_layout() # 自动调整布局防止重叠
plt.savefig("商品大类销售额.png") # 保存图表
# 按商品子类统计销售数据
subcategory_stats = data.groupby(['category', 'product_name']).agg({'order_id':'count','sales_amount':'sum'}).reset_index()
subcategory_stats.columns = ['产品类型', '产品子类', '订单数', '销售额'] # 重命名列
subcategory_stats['平均订单金额'] = subcategory_stats['销售额'] / subcategory_stats['订单数'] # 计算平均订单金额
subcategory_stats = subcategory_stats.sort_values('销售额', ascending=False) # 按销售额排序
# 显示Top3商品子类
print("产品子类统计:")
print(subcategory_stats.head(3)) # 输出前几行数据
# 可视化Top3商品子类销售额
top_subcategories = subcategory_stats.head(3)
plt.figure(figsize=(16, 10)) # 创建图形画布
sns.barplot(x='销售额', y='产品子类', hue='产品类型', data=top_subcategories, palette='viridis') # 绑制分类柱状图
plt.title('各产品子类销售额Top 3') # 设置图表标题
plt.xlabel('销售额(元)') # 设置X轴标签
plt.ylabel('产品子类') # 设置Y轴标签
plt.grid(axis='x') # 显示网格线
plt.tight_layout() # 自动调整布局防止重叠
plt.savefig("Top3子类销售额.png") # 保存图表
# 商品定价分析
data['价格段'] = pd.cut(data['price'], bins=[0, 100, 200, 500], labels=['0-100元', '100-200元', '200-500元']) #【要求2】
# 按价格段统计销售数据
price_range_stats = data.groupby('价格段').agg({'order_id':'count','sales_amount':'sum'}).reset_index()
price_range_stats.columns = ['价格段', '订单数', '销售额'] # 重命名列
price_range_stats['订单占比'] = price_range_stats['订单数'] / price_range_stats['订单数'].sum() * 100 # 计算订单占比
price_range_stats['销售额占比'] = price_range_stats['销售额'] / price_range_stats['销售额'].sum() * 100 # 计算销售额占比
# 显示价格段统计
print("价格段统计:")
print(price_range_stats) # 输出价格数据
# 可视化价格段销售情况
fig, (ax1, ax2) = plt.subplots(2, 1, figsize=(16, 14))
# 订单数占比柱状图
sns.barplot(x='价格段', y='订单占比', data=price_range_stats, palette='Blues_d', ax=ax1)
ax1.set_title('各价格段订单数占比') # 设置图表标题
ax1.set_xlabel('价格段') # 设置X轴标签
ax1.set_ylabel('订单数占比(%)') # 设置Y轴标签
ax1.grid(axis='y') # 设置网格线
# 销售额占比柱状图
sns.barplot(x='价格段', y='销售额占比', data=price_range_stats, palette='Reds_d', ax=ax2)
ax2.set_title('各价格段销售额占比') # 设置图表标题
ax2.set_xlabel('价格段') # 设置X轴标签
ax2.set_ylabel('销售额占比(%)') # 设置Y轴标签
ax2.grid(axis='y') # 设置网格线
plt.tight_layout() # 自动调整布局防止重叠
plt.savefig("价格段销售占比.png") # 保存图表
# 商品销售分布树形图
plt.figure(figsize=(16, 12))
category_sales = category_stats[['产品类型', '销售额']].copy() # 创建数据副本
category_sales['标签'] = category_sales['产品类型'] + '\n' + category_sales['销售额'].apply(lambda x: f'{x:,.0f}元') # 生成标签
squarify.plot(sizes=category_sales['销售额'], label=category_sales['标签'], alpha=0.8, color=sns.color_palette("viridis", len(category_sales))) # 绘制树形图
plt.axis('off') # 隐藏坐标轴
plt.title('各产品类型销售额树形图', fontsize=18) # 设置图表标题
plt.tight_layout() # 自动调整布局防止重叠
plt.savefig("产品销售额树形图.png") # 保存图表
# 商品季节性分析
seasonal_product = data.groupby(['order_season', 'category'])['sales_amount'].sum().reset_index() # 按季节和产品类型统计销售额
season_pivot = seasonal_product.pivot(index='category', columns='order_season', values='sales_amount') # 【要求3】
season_pct = season_pivot.div(season_pivot.sum(axis=1), axis=0) * 100 # 计算各季节占比
# 显示季节性销售占比
print("季节商品销售占比(%):")
print(season_pct) # 输出百分比数据
# 可视化季节性销售占比
plt.figure(figsize=(14, 10))
sns.heatmap(season_pct, annot=True, fmt='.1f', cmap='YlGnBu') # 绘制热力图
plt.title('各产品类型在不同季节的销售占比(%)') # 设置图表标题
plt.xlabel('季节') # 设置X轴标签
plt.ylabel('产品类型') # 设置Y轴标签
plt.tight_layout() # 自动调整布局防止重叠
plt.savefig("产品季节销售占比.png") # 保存图表
print("产品分析完成") # 输出产品分析完成
# 进行产品分析
product_analysis(data)29.3 产品结构分析
# 注:该代码块依赖的数据来自上方平台任务代码块,因其未执行,本块也无法执行
# ==================== 按品类统计销售数据 ====================
category_sales = data.groupby('category')['sales_amount'].sum().sort_values(ascending=False)
# 按产品类别分组,对销售额求和,然后按销售额降序排序
# sort_values(ascending=False)表示降序排列
# ==================== 创建柱状图 ====================
plt.figure(figsize=(12, 8)) # 创建12x8英寸的画布
bars = plt.bar(category_sales.index, category_sales.values, color='steelblue', alpha=0.7)
# 绘制柱状图,x轴为品类,y轴为销售额
# ==================== 添加数值标签 ====================
for bar in bars: # 遍历每个柱子
height = bar.get_height() # 获取柱子高度(销售额)
plt.text(
bar.get_x() + bar.get_width() / 2., # x坐标为柱子中心
height, # y坐标为柱子顶部
f'{height/10000:.1f}万', # 显示销售额,转换为万元单位,保留1位小数
ha='center', # 水平居中对齐
va='bottom', # 垂直底部对齐
fontsize=11 # 字体大小
)
plt.title('各品类销售总额', fontsize=16) # 设置图表标题
plt.xlabel('产品类别', fontsize=12) # 设置x轴标签
plt.ylabel('销售金额(元)', fontsize=12) # 设置y轴标签
plt.grid(axis='y', alpha=0.3) # 显示y轴网格线
plt.tight_layout() # 自动调整布局
plt.show() # 显示图表29.4 分析结论
- 销售趋势: 存在明显的周期性和季节性
- 核心品类: 茶叶是主要销售品类
- 移动平均: 平滑了短期波动,更易观察趋势
- 业务洞察: 需根据季节性调整库存和营销