当前位置: 首页 > news >正文

销售数据可视化分析项目

销售数据可视化分析项目

一、课程目标

本资料旨在教授如何使用 Python 进行销售数据的模拟生成、加载、分析和可视化,通过一系列实际需求案例,让学员掌握 Pandas、NumPy、Matplotlib 和 Seaborn 等库的基本使用方法。

二、课程内容

1. 导入必要的库和设置

import pandas as pd  # 导入 Pandas 库,用于数据处理和分析
import numpy as np  # 导入 NumPy 库,用于数值计算
import matplotlib.pyplot as plt  # 导入 Matplotlib 库,用于数据可视化
import os  # 导入 os 库,用于操作系统相关操作,如文件和目录管理
import seaborn as sns  # 导入 Seaborn 库,用于更美观的数据可视化
from datetime import datetime, timedelta  # 导入 datetime 和 timedelta 类,用于日期和时间处理# 设置中文字体,确保图表中的中文正常显示
plt.rcParams["font.family"] = ["SimHei"]
plt.rcParams["axes.unicode_minus"] = False  # 解决负号显示问题# 创建必要的目录
os.makedirs('data', exist_ok=True)  # 创建 data 目录,用于保存数据文件
os.makedirs('img', exist_ok=True)  # 创建 img 目录,用于保存图表文件

2. 需求 1: 模拟销售数据并保存为 CSV 文件

def generate_sales_data():"""生成模拟销售数据并保存为 CSV 文件"""# 设置随机种子,确保结果可重现np.random.seed(42)# 生成 1000 条销售记录n_samples = 1000# 生成日期数据(过去一年的随机日期)start_date = datetime.now() - timedelta(days=365)  # 计算一年前的日期dates = [start_date + timedelta(days=np.random.randint(0, 365)) for _ in range(n_samples)]  # 生成随机日期列表# 生成产品类别categories = ['电子产品', '服装', '食品', '家居', '图书']products = {'电子产品': ['手机', '笔记本电脑', '平板电脑', '耳机', '相机'],'服装': ['T恤', '牛仔裤', '连衣裙', '外套', '鞋子'],'食品': ['巧克力', '饼干', '水果', '饮料', '零食'],'家居': ['沙发', '餐桌', '床', '台灯', '吸尘器'],'图书': ['小说', '教材', '漫画', '传记', '工具书']}# 为每个类别设置基本价格范围base_prices = {'电子产品': (1000, 5000),'服装': (50, 500),'食品': (10, 100),'家居': (500, 3000),'图书': (20, 200)}# 生成销售数据data = []for _ in range(n_samples):category = np.random.choice(categories)  # 随机选择一个产品类别product = np.random.choice(products[category])  # 从选定类别中随机选择一个产品price = np.random.randint(base_prices[category][0], base_prices[category][1])  # 随机生成产品价格quantity = np.random.randint(1, 10)  # 随机生成销售数量region = np.random.choice(['华东', '华北', '华南', '西南', '西北', '东北', '中部'])  # 随机选择销售地区customer_type = np.random.choice(['个人', '企业'])  # 随机选择客户类型# 计算销售额revenue = price * quantity# 计算利润(电子产品和家居利润率较高,食品较低)if category in ['电子产品', '家居']:profit_rate = np.random.uniform(0.2, 0.4)  # 电子产品和家居的利润率在 20% - 40% 之间elif category == '食品':profit_rate = np.random.uniform(0.05, 0.15)  # 食品的利润率在 5% - 15% 之间else:profit_rate = np.random.uniform(0.1, 0.3)  # 其他类别的利润率在 10% - 30% 之间profit = revenue * profit_ratedata.append({'日期': dates[_].strftime('%Y-%m-%d'),  # 将日期转换为字符串格式'类别': category,'产品': product,'价格': price,'数量': quantity,'销售额': revenue,'利润': profit,'地区': region,'客户类型': customer_type})# 创建 DataFramedf = pd.DataFrame(data)# 保存数据到 CSV 文件file_path = 'data/sales_data.csv'df.to_csv(file_path, index=False, encoding='utf-8-sig')  # 将 DataFrame 保存为 CSV 文件print(f"销售数据已保存到 {file_path}")return df
generate_sales_data()
销售数据已保存到 data/sales_data.csv
日期类别产品价格数量销售额利润地区客户类型
02024-10-21食品水果42625215.987250华北企业
12025-06-24服装外套43583480525.229896华北企业
22025-04-07图书小说36932462.958137华南个人
32024-10-25食品巧克力78215619.201533东北个人
42024-09-20电子产品笔记本电脑36353109053797.384136华南个人
..............................
9952024-08-17电子产品笔记本电脑1132667921398.024382中部个人
9962025-04-29食品巧克力272547.623330西北企业
9972024-11-26图书小说173117327.368579华东企业
9982025-07-01服装牛仔裤2652530105.190907华南个人
9992025-06-08服装T恤29661776342.128440东北企业

1000 rows × 9 columns

3. 需求 2: 加载销售数据

def load_sales_data():"""加载销售数据"""try:df = pd.read_csv('data/sales_data.csv', encoding='utf-8-sig')  # 尝试读取 CSV 文件# 转换日期列df['日期'] = pd.to_datetime(df['日期'])  # 将日期列转换为 Pandas 的日期时间类型print("数据加载成功")return dfexcept FileNotFoundError:print("数据文件不存在,正在生成模拟数据...")return generate_sales_data()  # 如果文件不存在,调用 generate_sales_data 函数生成模拟数据
# 加载数据
df = load_sales_data()
数据加载成功

4. 需求 3: 按产品类别分析销售情况,生成透视表并保存为 CSV

def analyze_sales_by_category(df):"""按产品类别分析销售情况"""# 创建透视表pivot_table = pd.pivot_table(df,index='类别',  # 以产品类别为行索引values=['销售额', '利润', '数量'],  # 分析的数值列aggfunc={'销售额': 'sum',  # 对销售额进行求和'利润': 'sum',  # 对利润进行求和'数量': 'sum'  # 对数量进行求和})# 计算利润率pivot_table['利润率'] = (pivot_table['利润'] / pivot_table['销售额']).map(lambda x: f"{x:.2%}")  # 计算利润率并转换为百分比格式# 保存透视表到 CSVfile_path = 'data/category_analysis.csv'pivot_table.to_csv(file_path, encoding='utf-8-sig')  # 将透视表保存为 CSV 文件print(f"类别分析数据已保存到 {file_path}")# 可视化fig, axes = plt.subplots(1, 3, figsize=(18, 6))  # 创建包含 3 个子图的图形# 销售额柱状图pivot_table['销售额'].plot(kind='bar', ax=axes[0], title='按类别销售额', color='skyblue')  # 绘制销售额柱状图for p in axes[0].patches:axes[0].annotate(f'{p.get_height():,.0f}',  # 在柱子上添加销售额数值注释(p.get_x() + p.get_width() / 2., p.get_height()),ha='center', va='center',xytext=(0, 10),textcoords='offset points')# 利润柱状图pivot_table['利润'].plot(kind='bar', ax=axes[1], title='按类别利润', color='lightgreen')  # 绘制利润柱状图for p in axes[1].patches:axes[1].annotate(f'{p.get_height():,.0f}',  # 在柱子上添加利润数值注释(p.get_x() + p.get_width() / 2., p.get_height()),ha='center', va='center',xytext=(0, 10),textcoords='offset points')# 利润率饼图profit_rate = pivot_table['利润'] / pivot_table['销售额']profit_rate.plot(kind='pie', ax=axes[2], title='按类别利润率', autopct='%1.2f%%', ylabel='')  # 绘制利润率饼图plt.tight_layout()  # 调整子图布局plt.savefig('img/category_analysis.png')  # 保存图形为 PNG 文件plt.show()plt.close()  # 关闭图形return pivot_table
print("\n执行需求 3: 按产品类别分析销售情况")
category_analysis = analyze_sales_by_category(df)
执行需求 3: 按产品类别分析销售情况
类别分析数据已保存到 data/category_analysis.csv

matplotlib searborn

5. 需求 4: 按地区分析销售情况,生成交叉表并保存为 CSV

def analyze_sales_by_region(df):"""按地区分析销售情况"""# 创建交叉表 - 地区与产品类别的销售额cross_tab = pd.crosstab(index=df['地区'],  # 以地区为行索引columns=df['类别'],  # 以产品类别为列索引values=df['销售额'],  # 分析的数值列aggfunc='sum',  # 对销售额进行求和margins=True,  # 显示总计行和列margins_name='总计').fillna(0)  # 将缺失值填充为 0# 保存交叉表到 CSVfile_path = 'data/region_analysis.csv'cross_tab.to_csv(file_path, encoding='utf-8-sig')  # 将交叉表保存为 CSV 文件print(f"地区分析数据已保存到 {file_path}")# 可视化 - 热力图plt.figure(figsize=(12, 8))  # 创建图形sns.heatmap(cross_tab.iloc[:-1, :-1], annot=True, fmt='.0f', cmap='YlGnBu', cbar=True)  # 绘制热力图plt.title('地区与产品类别的销售额交叉表')  # 设置图形标题plt.tight_layout()  # 调整图形布局plt.savefig('img/region_heatmap.png')  # 保存图形为 PNG 文件plt.show()plt.close()  # 关闭图形return cross_tab
print("\n执行需求 4: 按地区分析销售情况")
region_analysis = analyze_sales_by_region(df)
执行需求 4: 按地区分析销售情况
地区分析数据已保存到 data/region_analysis.csv

matplotlib searborn

6. 需求 5: 按季度分析销售趋势

def analyze_sales_trend(df):"""按季度分析销售趋势"""# 提取季度信息df['季度'] = df['日期'].dt.to_period('Q')  # 从日期列中提取季度信息# 创建透视表trend_pivot = pd.pivot_table(df,index='季度',  # 以季度为行索引values=['销售额', '利润', '数量'],  # 分析的数值列aggfunc='sum'  # 对销售额、利润和数量进行求和).reset_index()  # 重置索引# 转换季度为字符串格式trend_pivot['季度'] = trend_pivot['季度'].astype(str)  # 将季度列转换为字符串类型# 保存趋势数据到 CSVfile_path = 'data/sales_trend.csv'trend_pivot.to_csv(file_path, index=False, encoding='utf-8-sig')  # 将透视表保存为 CSV 文件print(f"销售趋势数据已保存到 {file_path}")# 可视化 - 折线图plt.figure(figsize=(12, 6))  # 创建图形# 销售额趋势plt.subplot(2, 1, 1)  # 创建第一个子图plt.plot(trend_pivot['季度'], trend_pivot['销售额'], marker='o', color='skyblue', label='销售额')  # 绘制销售额折线图for x, y in zip(trend_pivot['季度'], trend_pivot['销售额']):plt.annotate(f'{y:,.0f}', (x, y), textcoords='offset points',  # 在折线上添加销售额数值注释xytext=(0, 10), ha='center')plt.title('季度销售趋势', loc = 'right')  # 设置子图标题plt.ylabel('销售额')  # 设置 y 轴标签plt.legend()  # 显示图例# 利润率趋势plt.subplot(2, 1, 2)  # 创建第二个子图profit_rate = trend_pivot['利润'] / trend_pivot['销售额']plt.plot(trend_pivot['季度'], profit_rate, marker='o', color='lightgreen', label='利润率')  # 绘制利润率折线图for x, y in zip(trend_pivot['季度'], profit_rate):plt.annotate(f'{y:.2%}', (x, y), textcoords='offset points',  # 在折线上添加利润率数值注释xytext=(0, 10), ha='center')plt.xlabel('季度')  # 设置 x 轴标签plt.ylabel('利润率')  # 设置 y 轴标签plt.legend()  # 显示图例plt.tight_layout()  # 调整子图布局plt.savefig('img/sales_trend.png')  # 保存图形为 PNG 文件plt.show()plt.close()  # 关闭图形return trend_pivot
print("\n执行需求 5: 按季度分析销售趋势")
sales_trend = analyze_sales_trend(df)
执行需求 5: 按季度分析销售趋势
销售趋势数据已保存到 data/sales_trend.csv

matplotlib searborn

7. 需求 6: 分析不同客户类型的购买偏好

def analyze_customer_preference(df):"""分析不同客户类型的购买偏好"""# 创建交叉表 - 客户类型与产品类别的购买数量preference_crosstab = pd.crosstab(index=df['客户类型'],  # 以客户类型为行索引columns=df['类别'],  # 以产品类别为列索引values=df['数量'],  # 分析的数值列aggfunc='sum',  # 对购买数量进行求和margins=True,  # 显示总计行和列margins_name='总计').fillna(0)  # 将缺失值填充为 0# 计算占比 - 使用 DataFrame.map 替代已弃用的 applymappreference_percentage = preference_crosstab.div(preference_crosstab['总计'], axis=0)  # 计算每个客户类型对各产品类别的购买数量占比for col in preference_percentage.columns:preference_percentage[col] = preference_percentage[col].map(lambda x: f"{x:.2%}")  # 将占比转换为百分比格式# 保存数据到 CSVfile_path = 'data/customer_preference.csv'preference_percentage.to_csv(file_path, encoding='utf-8-sig')  # 将数据保存为 CSV 文件print(f"客户偏好数据已保存到 {file_path}")# 可视化 - 堆叠柱状图plt.figure(figsize=(12, 6))  # 创建图形preference_crosstab.iloc[:-1, :-1].plot(kind='bar', stacked=True, ax=plt.gca())  # 绘制堆叠柱状图plt.title('不同客户类型的购买偏好')  # 设置图形标题plt.xlabel('客户类型')  # 设置 x 轴标签plt.ylabel('购买数量')  # 设置 y 轴标签plt.legend(title='产品类别')  # 显示图例plt.tight_layout()  # 调整图形布局plt.savefig('img/customer_preference.png')  # 保存图形为 PNG 文件plt.show()plt.close()  # 关闭图形return preference_percentage
print("\n执行需求 6: 分析不同客户类型的购买偏好")
customer_preference = analyze_customer_preference(df)
执行需求 6: 分析不同客户类型的购买偏好
客户偏好数据已保存到 data/customer_preference.csv

matplotlib searborn

8. 需求 7: 分析销售额最高的前10个产品

def analyze_top_products(df):"""分析销售额最高的前10个产品"""# 按产品分组并计算总销售额top_products = df.groupby('产品')['销售额'].sum().sort_values(ascending=False).head(10).reset_index()  # 按产品分组,计算总销售额,排序并取前 10 个产品# 保存数据到 CSVfile_path = 'data/top_products.csv'top_products.to_csv(file_path, index=False, encoding='utf-8-sig')  # 将数据保存为 CSV 文件print(f"Top 10 产品数据已保存到 {file_path}")# 可视化 - 水平柱状图plt.figure(figsize=(10, 6))  # 创建图形top_products.plot(kind='barh', x='产品', y='销售额', ax=plt.gca(), legend=False)  # 绘制水平柱状图plt.title('销售额最高的前10个产品')  # 设置图形标题plt.xlabel('销售额')  # 设置 x 轴标签plt.ylabel('产品')  # 设置 y 轴标签for i, v in enumerate(top_products['销售额']):plt.text(v + 1000, i, f'{v:,.0f}', va='center')  # 在柱子上添加销售额数值注释plt.tight_layout()  # 调整图形布局plt.savefig('img/top_products.png')  # 保存图形为 PNG 文件plt.show()plt.close()  # 关闭图形return top_products
print("\n执行需求 7: 分析销售额最高的前10个产品")
top_products = analyze_top_products(df)
执行需求 7: 分析销售额最高的前10个产品
Top 10 产品数据已保存到 data/top_products.csv

matplotlib searborn

9. 需求 8: 分析各地区的客户类型分布

def analyze_region_customer_type(df):"""分析各地区的客户类型分布"""# 创建透视表region_customer_pivot = pd.pivot_table(df,index='地区',  # 以地区为行索引columns='客户类型',  # 以客户类型为列索引values='销售额',  # 分析的数值列aggfunc='sum',  # 对销售额进行求和fill_value=0  # 将缺失值填充为 0)# 计算各地区客户类型占比region_customer_percentage = region_customer_pivot.div(region_customer_pivot.sum(axis=1), axis=0)  # 计算每个地区不同客户类型的销售额占比# 保存数据到 CSVfile_path = 'data/region_customer_type.csv'region_customer_percentage.to_csv(file_path, encoding='utf-8-sig')  # 将数据保存为 CSV 文件print(f"地区客户类型分布数据已保存到 {file_path}")# 可视化 - 饼图fig, axes = plt.subplots(2, 4, figsize=(16, 8))  # 创建包含 8 个子图的图形axes = axes.flatten()  # 将子图数组展平regions = region_customer_percentage.index.tolist()  # 获取地区列表for i, region in enumerate(regions):if i < len(axes):region_customer_percentage.loc[region].plot(kind='pie',ax=axes[i],autopct='%1.1f%%',title=f'{region} 客户类型分布',ylabel='')  # 为每个地区绘制客户类型分布饼图plt.tight_layout()  # 调整子图布局plt.savefig('img/region_customer_type.png')  # 保存图形为 PNG 文件plt.show()plt.close()  # 关闭图形return region_customer_percentage
print("\n执行需求 8: 分析各地区的客户类型分布")
region_customer_type = analyze_region_customer_type(df)
执行需求 8: 分析各地区的客户类型分布
地区客户类型分布数据已保存到 data/region_customer_type.csv

matplotlib searborn

10. 需求 9: 分析价格与销售额、利润的关系

def analyze_price_relationship(df):"""分析价格与销售额、利润的关系"""# 计算每个产品的平均价格、总销售额和总利润product_stats = df.groupby('产品').agg({'价格': 'mean',  # 计算每个产品的平均价格'销售额': 'sum',  # 计算每个产品的总销售额'利润': 'sum'  # 计算每个产品的总利润}).reset_index()  # 重置索引# 保存数据到 CSVfile_path = 'data/price_relationship.csv'product_stats.to_csv(file_path, index=False, encoding='utf-8-sig')  # 将数据保存为 CSV 文件print(f"价格关系数据已保存到 {file_path}")# 可视化 - 散点图矩阵g = sns.pairplot(product_stats, vars=['价格', '销售额', '利润'], hue='产品', palette='husl')  # 绘制散点图矩阵plt.suptitle('价格、销售额和利润的关系', y=1.02)  # 设置图形总标题plt.tight_layout()  # 调整图形布局plt.savefig('img/price_relationship.png')  # 保存图形为 PNG 文件plt.show()plt.close()  # 关闭图形# 计算相关系数矩阵correlation = product_stats[['价格', '销售额', '利润']].corr()  # 计算价格、销售额和利润之间的相关系数矩阵return correlation
print("\n执行需求 9: 分析价格与销售额、利润的关系")
price_relationship = analyze_price_relationship(df)
执行需求 9: 分析价格与销售额、利润的关系
价格关系数据已保存到 data/price_relationship.csv

matplotlib searborn

11. 需求 10: 综合分析报告 - 生成摘要统计信息

def generate_summary_report(df):"""生成综合分析报告"""# 计算关键指标total_sales = df['销售额'].sum()  # 计算总销售额total_profit = df['利润'].sum()  # 计算总利润total_quantity = df['数量'].sum()  # 计算总销售量average_price = df['价格'].mean()  # 计算平均价格profit_rate = total_profit / total_sales  # 计算利润率# 找出最畅销的产品类别和地区top_category = df.groupby('类别')['销售额'].sum().idxmax()  # 找出销售额最高的产品类别top_region = df.groupby('地区')['销售额'].sum().idxmax()  # 找出销售额最高的地区# 创建摘要数据summary_data = {'指标': ['总销售额', '总利润', '总销售量', '平均价格', '利润率', '最畅销类别', '最畅销地区'],'数值': [f'{total_sales:,.2f}',f'{total_profit:,.2f}',f'{total_quantity:,}',f'{average_price:,.2f}',f'{profit_rate:.2%}',top_category,top_region]}# 创建 DataFramesummary_df = pd.DataFrame(summary_data)# 保存摘要报告file_path = 'data/summary_report.csv'summary_df.to_csv(file_path, index=False, encoding='utf-8-sig')  # 将摘要报告保存为 CSV 文件print(f"摘要报告已保存到 {file_path}")return summary_df
print("\n执行需求 10: 生成综合分析报告")
summary_report = generate_summary_report(df)print("\n数据分析项目完成!")
print("数据文件已保存到 data 目录")
print("图表已保存到 img 目录")# 打印摘要报告
print("\n项目摘要报告:")
print(summary_report.to_string(index=False))
执行需求 10: 生成综合分析报告
摘要报告已保存到 data/summary_report.csv数据分析项目完成!
数据文件已保存到 data 目录
图表已保存到 img 目录项目摘要报告:指标           数值总销售额 4,839,533.00总利润 1,377,496.93总销售量        5,023平均价格       978.16利润率       28.46%
最畅销类别         电子产品
最畅销地区           西南
http://www.xdnf.cn/news/1100611.html

相关文章:

  • 专题:2025云计算与AI技术研究趋势报告|附200+份报告PDF、原数据表汇总下载
  • 如何选择数据可视化工具?从设计效率到图表表现力全解读
  • Spring之我见-Spring循环依赖为啥是三级缓存?
  • uniApp实战五:自定义组件实现便捷选择
  • Hadoop 用户入门指南:驾驭大数据的力量
  • 如何将文件从OPPO手机传输到电脑
  • crmeb多门店对接拉卡拉支付小程序聚合收银台集成全流程详解
  • UniApp 生命周期详解:从启动到销毁的完整指南
  • WHQL认证失败怎么办?企业如何高效申请
  • 前端开发—全栈开发
  • Python中类静态方法:@classmethod/@staticmethod详解和实战示例
  • Linux:多线程---同步生产者消费者模型
  • 人事系统选型与应用全攻略:从痛点解决到效率跃升的实战指南
  • 区块链应用场景深度解读:金融领域的革新与突破
  • 资源分享-FPS, 矩阵, 骨骼, 绘制, 自瞄, U3D, UE4逆向辅助实战视频教程
  • 将Blender、Three.js与Cesium集成构建物联网3D可视化系统
  • 【SpringAI】6.向量检索(redis)
  • javaweb之相关jar包和前端包下载。
  • PHY模式,slave master怎么区分
  • 7.11文件和异常
  • 什么是进程、什么是线程(进程、线程的全方面解析)
  • 界面组件DevExpress WPF中文教程:Grid - 如何检查节点?
  • 在 React Three Fiber 中实现 3D 模型点击扩散波效果
  • JavaWeb笔记二
  • 企业级配置:Azure 邮件与 Cloudflare 域名解析的安全验证落地详解
  • CReFT-CAD 笔记 带标注工程图dxf,png数据集
  • JVM 内存结构
  • 每天一个前端小知识 Day 29 - WebGL / WebGPU 数据可视化引擎设计与实践
  • 人工智能-基础篇-29-什么是低代码平台?
  • AI问答之手机相机专业拍照模式的主要几个参数解释