# Python实现销售数据统计与可视化工具:从CSV到图表的全流程解析


背景介绍

对于小型企业或店铺而言,快速分析产品销售表现是优化库存、制定营销策略的关键。本文将带你用Python开发一个销售数据统计与可视化工具,通过读取CSV销售数据,自动统计各产品的销量与销售额,并以直观的柱状图展示结果。该工具不仅能帮助初学者掌握文件处理+数据统计+可视化的完整流程,还能解决matplotlib中文乱码等常见问题。

思路分析

我们的工具将分三步实现:
1. 数据读取:使用csv模块读取CSV文件,处理每行数据的产品名称、销售数量和单价。
2. 数据统计:通过字典按产品名称分组,累加总销量、计算总销售额(销量×单价)。
3. 可视化展示:利用matplotlib绘制双柱状图(子图布局),并配置中文显示、图表美化(如标签旋转、颜色设置)。

代码实现

下面是完整的代码实现,包含详细注释:

import csv
import matplotlib.pyplot as plt

def read_and_analyze(csv_path):
    """读取CSV文件并按产品统计销量和销售额"""
    product_stats = {}  # 存储结构:{产品名: (总销量, 总销售额)}
    with open(csv_path, 'r', encoding='utf-8') as f:
        reader = csv.reader(f)
        next(reader)  # 跳过表头行
        for row in reader:
            # 处理数据不完整的情况(空值、列数不足)
            if len(row) < 3 or not row[1].strip() or not row[2].strip():
                print(f"警告:数据行{row}不完整/有空值,已跳过")
                continue
            product = row[0]
            try:
                quantity = int(row[1])  # 转换为整数(销量)
                price = float(row[2])  # 转换为浮点数(单价)
            except ValueError:
                print(f"警告:数据行{row}的数量/单价格式错误,已跳过")
                continue
            # 累加销量和销售额
            if product in product_stats:
                prev_q, prev_r = product_stats[product]
                product_stats[product] = (prev_q + quantity, prev_r + quantity * price)
            else:
                product_stats[product] = (quantity, quantity * price)
    return product_stats

def visualize(product_stats, save_path=None):
    """绘制销量和销售额的双柱状图"""
    # 提取数据
    products = list(product_stats.keys())
    quantities = [stats[0] for stats in product_stats.values()]
    revenues = [stats[1] for stats in product_stats.values()]

    # 配置matplotlib中文显示(需系统有对应字体,如SimHei)
    plt.rcParams["font.family"] = ["SimHei", "WenQuanYi Micro Hei", "Heiti TC"]
    plt.rcParams["axes.unicode_minus"] = False  # 解决负号显示问题

    # 创建1行2列的子图,调整画布大小
    fig, (ax1, ax2) = plt.subplots(1, 2, figsize=(12, 6))

    # 绘制销量对比图(左子图)
    ax1.bar(products, quantities, color='#5DA5DA', edgecolor='black', zorder=3)
    ax1.set_title('各产品销量对比')
    ax1.set_xlabel('产品名称')
    ax1.set_ylabel('销量(件)')
    ax1.tick_params(axis='x', rotation=45)  # 旋转x轴标签防止重叠
    ax1.grid(axis='y', linestyle='--', alpha=0.7)  # 添加水平网格线

    # 绘制销售额对比图(右子图)
    ax2.bar(products, revenues, color='#FAA43A', edgecolor='black', zorder=3)
    ax2.set_title('各产品销售额对比')
    ax2.set_xlabel('产品名称')
    ax2.set_ylabel('销售额(元)')
    ax2.tick_params(axis='x', rotation=45)
    ax2.grid(axis='y', linestyle='--', alpha=0.7)

    # 隐藏左右上三边的边框,使图表更简洁
    for ax in [ax1, ax2]:
        ax.spines['top'].set_visible(False)
        ax.spines['right'].set_visible(False)
        ax.spines['left'].set_visible(False)

    # 调整布局,防止标签被截断
    plt.tight_layout()

    if save_path:
        plt.savefig(save_path, dpi=300, bbox_inches='tight')
        print(f"图表已保存至:{save_path}")
    else:
        plt.show()

def main():
    """主函数:处理用户输入,调用数据读取和可视化"""
    try:
        csv_path = input("请输入CSV文件路径(例如:sales_data.csv):")
        # 读取并分析数据
        stats = read_and_analyze(csv_path)
        if not stats:
            print("错误:未统计到有效数据,请检查CSV文件格式。")
            return
        # 打印统计结果
        print("\n===== 销售统计结果 =====")
        for product, (q, r) in stats.items():
            print(f"{product}:总销量={q},总销售额={r:.2f}")
        # 可视化
        save_choice = input("\n是否需要保存图表?(y/n) ")
        if save_choice.lower() == 'y':
            save_path = input("请输入保存路径(例如:sales_chart.png):")
            visualize(stats, save_path)
        else:
            visualize(stats)
    except FileNotFoundError:
        print(f"错误:文件{csv_path}不存在,请检查路径。")
    except Exception as e:
        print(f"发生未知错误:{e}")

if __name__ == "__main__":
    main()

代码解析

  1. 数据读取与统计read_and_analyze函数通过csv.reader逐行读取数据,跳过表头后处理每行数据。使用字典product_stats按产品名称分组,累加销量、计算销售额,并处理空值和格式错误(如非数字的销量/单价)。

  2. 可视化配置visualize函数中,我们通过plt.rcParams配置中文显示(需系统安装对应字体,如SimHei),创建1行2列的子图(subplots),分别绘制销量和销售额的柱状图。通过grid添加网格线、spines隐藏多余边框,使图表更美观。

  3. 用户交互main函数处理用户输入的CSV路径,调用统计和可视化函数,并支持选择是否保存图表(需用户输入保存路径)。

运行示例

假设CSV文件sales_data.csv内容如下:

产品名称,销售数量,单价
产品A,10,20.5
产品B,5,30.0
产品C,8,15.7

运行程序后,控制台输出:

===== 销售统计结果 =====
产品A:总销量=10,总销售额=205.00
产品B:总销量=5,总销售额=150.00
产品C:总销量=8,总销售额=125.60

同时弹出双柱状图,左图展示销量对比,右图展示销售额对比(x轴标签旋转45度,图表带网格线和简洁边框)。

拓展挑战

  • 主题切换:可通过plt.style.use('dark_background')或自定义颜色配置实现深色主题。
  • 异常处理增强:对CSV中“销售数量”或“单价”为空的情况,可设置默认值(如0)或提示用户修正。
  • 批量处理:支持读取多个CSV文件,合并统计结果后可视化。

总结

本项目通过Python的csvmatplotlib库,实现了“文件读取→数据统计→可视化”的完整流程。核心难点在于中文显示配置(解决matplotlib乱码)和数据异常处理(空值、格式错误)。通过该项目,初学者可系统掌握文件处理、数据聚合、可视化的实践技巧,为更复杂的数据分析项目打下基础。

如果需要进一步优化,可尝试引入pandas简化数据处理(如df.groupby().agg()),或用seaborn美化图表风格。

希望这篇教程能帮助你掌握Python数据处理与可视化的核心技能!


发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注