开头先聊一个很多初学者都会遇到的场景:想用 Python 做数据分析,上网一搜资料,发现教程东一个西一个,NumPy 讲一点、Pandas 讲一点、Matplotlib 再讲一点,但始终没有人告诉你这三个库到底怎么串成一条完整的工作流。更头疼的是,跟着教程敲代码,结果环境装不上、数据读不进来、图表中文乱码,每一步都在劝退。
这篇文章就围绕NumPy + Pandas + Matplotlib这套 Python 数据分析三件套,整理一份从零基础到项目实战的完整教程。不需要你有数学基础,也不需要你先学完 Python 全部门语法,只要会最基本的 Python 写法,就能跟着一步步完成数据读取、清洗、分析和可视化。
文中所有代码都基于常见版本编写,命令和示例可以复制后直接运行。读完你不仅能掌握三个库的核心用法,还能独立完成一个小型数据分析项目。
1. 三个库分别解决什么问题
先建立整体认知。很多新手把 NumPy、Pandas、Matplotlib 混在一起学,越学越乱,根源在于不知道每个库的定位。
1.1 NumPy:数值计算的底层引擎
NumPy(Numerical Python)是 Python 科学计算的基础库,它提供了高性能的多维数组对象ndarray,以及大量的数学函数。
为什么不用 Python 自带的 list 做数值计算?因为 list 在存储和运算上有两个明显短板:一是元素类型不固定导致内存浪费,二是循环计算效率低。NumPy 的数组在内存中连续存储,配合向量化运算,能比 Python 原生循环快几个数量级。
import numpy as np # Python list 计算平方 data_list = [1, 2, 3, 4, 5] result_list = [x ** 2 for x in data_list] # NumPy 数组计算平方 data_array = np.array([1, 2, 3, 4, 5]) result_array = data_array ** 2 print(result_list) print(result_array)输出:
[1, 4, 9, 16, 25] [1 4 9 16 25]两种方式结果一样,但 NumPy 写法更简洁;数据量越大,性能差距越明显。数据分析中所有数值计算,底层几乎都离不开 NumPy。
1.2 Pandas:表格数据处理利器
Pandas 是构建在 NumPy 之上的数据分析库,核心数据结构是Series(一维序列)和DataFrame(二维表格)。它解决的问题是:如何方便地读取、筛选、聚合、清洗表格数据。
可以这样理解:NumPy 提供“数组”,Pandas 提供“带标签的表格”。现实中绝大多数数据都是以表格形式存在的,比如 Excel 表格、CSV 文件、数据库查询结果。Pandas 就是 Python 世界里操作这些表格的最主流工具。
Pandas 最常用的操作包括:
- 读取 CSV、Excel、JSON 等文件。
- 筛选指定行和列。
- 处理缺失值和重复值。
- 按某列分组后做统计。
- 合并多张表。
1.3 Matplotlib:把数据变成图表
Matplotlib 是 Python 最经典的绘图库,它负责把分析结果可视化成折线图、柱状图、散点图、直方图等。为什么可视化很重要?因为人对图表的敏感度远高于对数字表格的敏感度。一份销售数据放在表格里,你可能看不出趋势;画成折线图后,增长和波动一眼就能发现。
Matplotlib 的设计理念是“完全控制绘图细节”。你可以自定义坐标轴、颜色、图例、标题、字体、刻度等所有元素。它也提供了pyplot子模块,模拟 MATLAB 的绘图方式,适合快速出图。
1.4 三者如何配合
一套典型的数据分析流程是这样的:
- 用 Pandas 读取数据文件。
- 用 Pandas 完成数据清洗和预处理。
- 用 NumPy 做部分数值计算和统计运算。
- 用 Matplotlib 把分析结果画成图表。
实际工作中,三个库经常在同一个脚本里互相配合。这也是为什么学习时要先懂 NumPy,再学 Pandas,最后学 Matplotlib——因为 Pandas 的数据结构底层依赖 NumPy,Matplotlib 又经常直接处理 NumPy 数组和 Pandas 列数据。
2. 环境准备与安装
开始写代码之前,先把环境搭好。这里以最常见的方式演示,操作系统以 Windows 为例,macOS 和 Linux 下的命令基本一致。
2.1 安装 Python
首先确认电脑上已经安装了 Python 3.8 及以上版本。打开命令行(Windows 下是 CMD 或 PowerShell),输入:
python --version如果没有安装 Python,可以到 Python 官网下载安装包。安装时务必勾选Add Python to PATH,否则后续 pip 命令可能找不到。
2.2 安装三个库
推荐使用 pip 安装:
pip install numpy pandas matplotlib如果下载速度慢,可以使用国内镜像源:
pip install numpy pandas matplotlib -i https://pypi.tuna.tsinghua.edu.cn/simple安装完成后,验证是否成功:
import numpy as np import pandas as pd import matplotlib.pyplot as plt print("NumPy 版本:", np.__version__) print("Pandas 版本:", pd.__version__) print("Matplotlib 版本:", plt.matplotlib.__version__)如果能打印出版本号,说明环境已经就绪。
2.3 选择开发工具
新手推荐使用 Anaconda 或 VS Code:
- Anaconda 自带 NumPy、Pandas、Matplotlib 和 Jupyter Notebook,省去手动安装的麻烦。
- VS Code 轻量,配合 Python 插件体验很好,适合长期写项目。
本文示例代码在普通 Python 脚本文件和 Jupyter Notebook 中都可以运行。如果使用 Jupyter Notebook,图表会直接显示在单元格下方;如果使用脚本文件,需要调用plt.show()展示图表。
3. NumPy 核心用法详解
NumPy 的内容非常多,初学者不需要全部掌握。以下挑选数据分析中最常用的几个知识点:创建数组、数组切片、布尔筛选、通用函数和统计计算。
3.1 创建 NumPy 数组
最直接的创建方式是从列表转换:
import numpy as np # 一维数组 arr1 = np.array([1, 2, 3, 4, 5]) print(arr1, arr1.shape) # 二维数组 arr2 = np.array([[1, 2, 3], [4, 5, 6]]) print(arr2, arr2.shape) # 全零数组 zeros = np.zeros((2, 3)) print(zeros) # 等差数组 arr_range = np.arange(0, 10, 2) # 从0到10,步长为2 print(arr_range)shape属性返回数组的维度形状。(2, 3)表示 2 行 3 列。理解 shape 对后续操作非常重要,比如矩阵转置、reshape 都和 shape 直接相关。
3.2 数组切片(重点)
NumPy 切片语法和 Python list 类似,但在多维数组上更强大。这是热搜词中出现频率很高的知识点,也是新手最容易写错的地方。
import numpy as np arr = np.array([[1, 2, 3, 4], [5, 6, 7, 8], [9, 10, 11, 12]]) # 取第 1 行(索引从 0 开始) print(arr[0, :]) # 输出 [1 2 3 4] # 取第 2 列 print(arr[:, 1]) # 输出 [2 6 10] # 取前两行、前两列 print(arr[:2, :2]) # 输出 [[1 2] [5 6]] # 步长为 2 取行 print(arr[::2, :]) # 输出第 0 行和第 2 行切片的语法是数组[行起始:行结束:行步长, 列起始:列结束:列步长]。需要注意,切片结果是原数组的视图,修改切片会影响原数组。如果希望得到一份独立副本,用.copy()。
sub = arr[:2, :2].copy() sub[0, 0] = 999 print(arr[0, 0]) # 仍然是 13.3 布尔筛选
布尔筛选是数据分析中极为常用的操作,用于按条件筛选数组元素:
import numpy as np scores = np.array([65, 80, 92, 58, 73, 88]) # 筛选大于等于 80 的分数 high_scores = scores[scores >= 80] print(high_scores) # 输出 [80 92 88] # 筛选 60 到 85 之间的分数 mid_scores = scores[(scores >= 60) & (scores <= 85)] print(mid_scores) # 输出 [65 80 73]条件判断会生成一个布尔数组,NumPy 自动把布尔值为True的元素取出来。多个条件组合时,用&(且)和|(或),每个条件必须加括号,这一点和 Python 原生的and、or不同。
3.4 统计计算函数
数据分析离不开统计量,NumPy 提供了大量现成函数:
import numpy as np data = np.array([12, 18, 25, 30, 42, 55, 68]) print("总和:", np.sum(data)) print("平均值:", np.mean(data)) print("标准差:", np.std(data)) print("最小值:", np.min(data)) print("最大值:", np.max(data)) print("中位数:", np.median(data))二维数组可以指定按行或按列计算:
matrix = np.array([[1, 2, 3], [4, 5, 6]]) print("按列求和:", np.sum(matrix, axis=0)) # 输出 [5 7 9] print("按行求和:", np.sum(matrix, axis=1)) # 输出 [6 15]axis=0表示沿着行的方向压缩,结果是每列的和;axis=1表示沿着列的方向压缩,结果是每行的和。记忆技巧:指定 axis 后,该维度的长度会变成 1。
4. Pandas 核心用法详解
Pandas 是数据分析流程中使用频率最高的库。这一节重点讲 Series、DataFrame、读取数据、清洗数据和分组聚合。
4.1 Series 和 DataFrame
Series 是带索引的一维数组。可以把它理解为“带标签的列”。
import pandas as pd s = pd.Series([85, 90, 78, 92], index=["语文", "数学", "英语", "物理"]) print(s)输出:
语文 85 数学 90 英语 78 物理 92 dtype: int64DataFrame 是二维表格数据结构,由多列 Series 组成,是 Pandas 中最常用的对象。
import pandas as pd df = pd.DataFrame({ "姓名": ["张三", "李四", "王五"], "年龄": [23, 28, 25], "城市": ["北京", "上海", "广州"] }) print(df)输出:
姓名 年龄 城市 0 张三 23 北京 1 李四 28 上海 2 王五 25 广州4.2 读取外部数据
Pandas 支持读取多种格式的文件。最常用的是 CSV 和 Excel。
import pandas as pd # 读取 CSV 文件 df_csv = pd.read_csv("sales_data.csv", encoding="utf-8") # 读取 Excel 文件 df_excel = pd.read_excel("sales_data.xlsx", sheet_name="Sheet1")读取后先查看数据概况,这是数据分析的第一步:
# 查看前 5 行 print(df.head()) # 查看数据基本信息 print(df.info()) # 查看数值列的描述统计 print(df.describe())df.info()会显示每列的非空数量、数据类型和内存占用,是判断数据质量的重要依据。
4.3 筛选和排序
DataFrame 的列筛选非常简单:
# 取单列,返回 Series ages = df["年龄"] # 取多列,返回 DataFrame sub_df = df[["姓名", "城市"]]行筛选通常使用布尔条件:
# 筛选年龄大于 24 的记录 result = df[df["年龄"] > 24] print(result)排序用sort_values:
# 按年龄降序排列 df_sorted = df.sort_values("年龄", ascending=False) print(df_sorted)4.4 处理缺失值和重复值
真实数据很少是干净的,缺失值、重复值几乎必然出现。
import pandas as pd import numpy as np df = pd.DataFrame({ "订单号": ["A001", "A002", "A003", "A003"], "金额": [100, np.nan, 300, 300], "城市": ["北京", "上海", None, "广州"] })查看缺失情况:
print(df.isnull().sum())处理缺失值的两种主流方式:
# 方式一:删除有缺失值的行 df_dropna = df.dropna() # 方式二:用固定值填充 df_fillna = df.fillna({"金额": 0, "城市": "未知"})处理重复值:
# 删除重复行,保留第一条 df_unique = df.drop_duplicates(subset=["订单号"])热搜词中有“pandas如果指定两列的值均相同,则取第一条数据即可”,对应的就是drop_duplicates(subset=[...])的用法。比如有两列分别是“用户ID”和“商品ID”,希望同一个用户对同一个商品只保留一条记录,就可以把这俩列名放进subset参数里。
4.5 分组聚合
分组聚合是统计分析中最核心的操作。它对应 SQL 里的GROUP BY。
import pandas as pd df = pd.DataFrame({ "部门": ["技术部", "技术部", "市场部", "市场部", "市场部"], "员工": ["小张", "小李", "小刘", "小赵", "小孙"], "薪资": [12000, 15000, 9000, 11000, 9500] }) # 按部门分组,求薪资平均值 result = df.groupby("部门")["薪资"].mean() print(result)输出:
市场部 9833.333333 技术部 13500.000000 Name: 薪资, dtype: float64如果想要多个统计量,可以用agg:
result = df.groupby("部门")["薪资"].agg(["mean", "sum", "count", "max"]) print(result)4.6 合并多张表
实际工作中数据往往分散在多张表里。Pandas 的merge函数类似 SQL 的 JOIN:
import pandas as pd orders = pd.DataFrame({ "订单号": ["A001", "A002", "A003"], "用户ID": [1, 2, 1] }) users = pd.DataFrame({ "用户ID": [1, 2, 3], "姓名": ["张三", "李四", "王五"] }) merged = pd.merge(orders, users, on="用户ID", how="left") print(merged)how参数控制连接方式:left保留左表全部记录,inner只保留两边都匹配的记录,right保留右表全部记录,outer保留两边所有记录。
5. Matplotlib 数据可视化详解
Matplotlib 的绘图逻辑可以拆成三步:准备数据、调用绘图函数、调整细节。下面先讲最基础的绘图方式,再讲实际项目中必备的进阶技巧。
5.1 折线图
折线图适合展示趋势变化,比如每日销售额、温度变化、股票价格。
import matplotlib.pyplot as plt # 解决中文乱码 plt.rcParams["font.sans-serif"] = ["SimHei"] plt.rcParams["axes.unicode_minus"] = False days = ["周一", "周二", "周三", "周四", "周五", "周六", "周日"] sales = [120, 150, 138, 165, 190, 220, 210] plt.figure(figsize=(8, 5)) plt.plot(days, sales, marker="o", linestyle="-", color="blue") plt.title("一周销售额变化") plt.xlabel("星期") plt.ylabel("销售额(元)") plt.grid(True, linestyle="--", alpha=0.5) plt.show()这里需要特别说明两行中文字体设置:
plt.rcParams["font.sans-serif"] = ["SimHei"] plt.rcParams["axes.unicode_minus"] = False第一行指定中文字体,如果不设置,图表中的中文会显示成方块;第二行解决负号显示异常的问题。这一对配置是 Matplotlib 中文绘图的标配。
5.2 柱状图
柱状图适合对比不同类别的数值大小。
import matplotlib.pyplot as plt plt.rcParams["font.sans-serif"] = ["SimHei"] plt.rcParams["axes.unicode_minus"] = False categories = ["手机", "电脑", "平板", "耳机"] sales = [3500, 5200, 1800, 2600] plt.figure(figsize=(8, 5)) plt.bar(categories, sales, color=["#4C72B0", "#55A868", "#C44E52", "#8172B3"]) plt.title("各品类销量对比") plt.xlabel("品类") plt.ylabel("销量(件)") plt.show()5.3 散点图
散点图适合观察两个变量之间的关系,比如广告投入和销售额是否有正相关性。
import matplotlib.pyplot as plt import numpy as np np.random.seed(42) ad_cost = np.random.randint(100, 500, 50) sales = ad_cost * 2 + np.random.randint(-50, 50, 50) plt.figure(figsize=(8, 5)) plt.scatter(ad_cost, sales, alpha=0.6, color="darkorange") plt.title("广告费用与销售额关系") plt.xlabel("广告费用(元)") plt.ylabel("销售额(元)") plt.show()alpha参数控制透明度,当数据点重叠较多时,降低透明度可以更清楚地看到点密度。
5.4 直方图
直方图用于查看数据的分布情况,比如员工年龄分布、订单金额分布。
import matplotlib.pyplot as plt import numpy as np np.random.seed(10) ages = np.random.normal(30, 5, 1000) plt.figure(figsize=(8, 5)) plt.hist(ages, bins=30, edgecolor="black", alpha=0.7) plt.title("年龄分布直方图") plt.xlabel("年龄") plt.ylabel("人数") plt.show()bins参数控制分箱数量,即把数据分成多少个区间。bins 太小时分布形状过于粗糙,bins 太大时又可能过于细碎,需要根据数据量调整。
5.5 子图与画布大小
实际分析中经常需要在一张图里展示多个子图。用subplot可以实现:
import matplotlib.pyplot as plt plt.rcParams["font.sans-serif"] = ["SimHei"] plt.rcParams["axes.unicode_minus"] = False fig, axes = plt.subplots(2, 2, figsize=(10, 8)) # 第一个子图:折线图 axes[0, 0].plot([1, 2, 3, 4], [10, 25, 15, 30]) axes[0, 0].set_title("折线图") # 第二个子图:柱状图 axes[0, 1].bar(["A", "B", "C"], [5, 8, 3]) axes[0, 1].set_title("柱状图") # 第三个子图:散点图 axes[1, 0].scatter([1, 2, 3, 4], [20, 18, 25, 30]) axes[1, 0].set_title("散点图") # 第四个子图:直方图 axes[1, 1].hist([1, 2, 2, 3, 3, 3, 4, 4, 5], bins=5) axes[1, 1].set_title("直方图") plt.tight_layout() plt.show()plt.subplots(2, 2)返回一个包含 2 行 2 列子图的画布,axes是子图对象组成的数组。figsize=(10, 8)控制整个画布的大小,对应热搜词中的“matplotlib画布大小”问题。
5.6 统一 x 轴和 y 轴比例
有些场景下需要 x 轴和 y 轴刻度比例一致,比如绘制几何图形、地图坐标时,否则图形会发生拉伸变形。热搜词中有“matplotlib中x轴和y轴比例统一”,对应方法是set_aspect("equal"):
import matplotlib.pyplot as plt plt.figure(figsize=(5, 5)) plt.plot([0, 1], [0, 1], marker="o") plt.gca().set_aspect("equal") plt.show()set_aspect("equal")会让 1 个 x 轴单位在屏幕上占据的像素长度等于 1 个 y 轴单位占据的像素长度。不加这个设置时,Matplotlib 会根据画布比例自动拉伸坐标轴,可能导致圆形变成椭圆。
6. 完整实战:电商销售数据分析
下面把三个库串起来,完成一个完整的小项目。场景设定为一家电商公司,数据有两张表:一张是订单明细表,一张是商品信息表。任务包括数据读取、清洗、聚合、可视化和结论输出。
6.1 准备测试数据
为了让大家能直接复现,这里先用 Pandas 在内存中生成模拟数据,不需要额外下载文件。
import pandas as pd import numpy as np np.random.seed(2024) # 生成订单数据 orders = pd.DataFrame({ "订单号": [f"ORD{i:04d}" for i in range(1, 301)], "商品ID": np.random.choice(["P001", "P002", "P003", "P004"], 300), "销量": np.random.randint(1, 10, 300), "单价": np.random.choice([499, 899, 1299, 2499], 300), "城市": np.random.choice(["北京", "上海", "广州", "深圳", "杭州"], 300) }) # 生成商品信息表 products = pd.DataFrame({ "商品ID": ["P001", "P002", "P003", "P004"], "商品名称": ["无线耳机", "智能手表", "平板电脑", "旗舰手机"], "分类": ["数码配件", "穿戴设备", "平板电脑", "手机"] }) print(orders.head()) print(products.head())6.2 数据清洗与合并
# 添加销售额列 orders["销售额"] = orders["销量"] * orders["单价"] # 合并商品信息 df = pd.merge(orders, products, on="商品ID", how="left") # 检查缺失值 print(df.isnull().sum()) # 查看数据类型 print(df.dtypes)6.3 多维度分析
第一个维度:各城市的销售总额。
city_sales = df.groupby("城市")["销售额"].sum().sort_values(ascending=False) print(city_sales)第二个维度:各商品分类的销售份额。
category_sales = df.groupby("分类")["销售额"].sum().sort_values(ascending=False) print(category_sales)第三个维度:不同价格区间的销量分布。这里用 NumPy 计算并添加分组标签。
bins = [0, 500, 1000, 2000, 3000] labels = ["0-500", "500-1000", "1000-2000", "2000-3000"] df["价格区间"] = pd.cut(df["单价"], bins=bins, labels=labels) price_dist = df.groupby("价格区间", observed=False)["销量"].sum() print(price_dist)6.4 可视化输出
import matplotlib.pyplot as plt plt.rcParams["font.sans-serif"] = ["SimHei"] plt.rcParams["axes.unicode_minus"] = False fig, axes = plt.subplots(2, 2, figsize=(12, 9)) # 图1:城市销售额柱状图 axes[0, 0].bar(city_sales.index, city_sales.values, color="#4C72B0") axes[0, 0].set_title("各城市销售额") axes[0, 0].set_xlabel("城市") axes[0, 0].set_ylabel("销售额(元)") # 图2:分类销售额饼图 axes[0, 1].pie(category_sales.values, labels=category_sales.index, autopct="%.1f%%") axes[0, 1].set_title("各分类销售份额") # 图3:价格区间销量柱状图 axes[1, 0].bar(price_dist.index.astype(str), price_dist.values, color="#55A868") axes[1, 0].set_title("价格区间销量分布") axes[1, 0].set_xlabel("价格区间(元)") axes[1, 0].set_ylabel("销量(件)") # 图4:销量与单价的散点图 axes[1, 1].scatter(df["单价"], df["销量"], alpha=0.4, color="darkorange") axes[1, 1].set_title("单价与销量关系") axes[1, 1].set_xlabel("单价(元)") axes[1, 1].set_ylabel("销量(件)") plt.tight_layout() plt.show()6.5 结果说明
运行代码后,你能得到四张图表:
- 第一张图展示各城市的销售额排名,可以直接看到哪个城市贡献最大。
- 第二张图展示分类销售份额,能快速判断核心品类。
- 第三张图展示价格区间与销量的关系,可以看出哪个价位最受欢迎。
- 第四张图展示单价和销量的散点分布,用于观察是否存在明显相关性。
这个例子虽然用的是模拟数据,但覆盖了真实项目中至少 80% 的日常操作:生成/读取数据、合并表、分组统计、数值分箱、多子图可视化。
7. 常见问题与排查思路
下面整理新手最常遇到的几个问题,每个问题都给出排查思路和解决方案。
| 问题现象 | 常见原因 | 解决思路 |
|---|---|---|
ModuleNotFoundError: No module named 'numpy' | 库未安装或安装了到错误环境 | 先确认当前 Python 环境,再执行pip install numpy |
| Matplotlib 图表中文显示为方块 | 系统缺少中文字体设置 | 设置plt.rcParams["font.sans-serif"] = ["SimHei"] |
| 图表负号显示异常 | 默认字体不支持负号 | 设置plt.rcParams["axes.unicode_minus"] = False |
| Pandas 读取 CSV 报编码错误 | 文件编码不是 UTF-8 | 指定编码,如read_csv("file.csv", encoding="gbk") |
| 删除重复行后结果仍然有重复 | subset参数没指定或设置错误 | 确认重复判断的列名是否写全 |
FutureWarning提示分组聚合行为变更 | Pandas 版本升级后的兼容性提示 | 阅读提示内容,按照新版 API 调整代码 |
| NumPy 切片后修改原数组跟着变化 | 切片是视图而不是副本 | 如需独立数据,使用.copy() |
matplotlib绘制不出图 | 缺少plt.show()或后端问题 | 脚本文件需要在末尾调用plt.show() |
这里重点说两个高频问题。
7.1 安装了库但仍然报 ModuleNotFoundError
这种情况十次有九次是 Python 环境不对。很多电脑同时装了多个 Python 版本,比如 Python 3.9 和 3.11,你用pip install装到了 A 环境,但运行脚本用的是 B 环境。
排查命令:
pip --version python --version如果 pip 和 python 的版本信息对应不上,可以改用:
python -m pip install numpy pandas matplotlibpython -m pip会确保把包安装到当前python命令对应的环境里。
7.2 Pandas 版本兼容问题
热搜词中有“python3.10与哪个pandas版本适配”这类疑问。Pandas 对 Python 版本有明确的支持范围,新版本 Pandas 可能不支持旧版本 Python。如果安装时遇到依赖解析错误,可以安装指定版本:
pip install pandas==2.0.3实际项目中不要盲目追求最新版本,优先选择与当前 Python 版本兼容的稳定版本。安装前可以通过python --version确认 Python 版本,再查询对应 Pandas 版本支持情况。
8. 最佳实践与工程建议
8.1 数据清洗要放在第一步
拿到数据后不要急于做分析或画图,先执行一套固定的清洗动作:
检查缺失值、检查重复值、检查数据类型、检查字段范围是否合理。这四步做完,再进入分析环节。很多图表的异常,根源都在数据本身不干净。
8.2 遵循“先小后大”的调试原则
写代码时先用小数据集跑通流程,再切换到完整数据。比如上述实战中,先用 10 行测试数据验证代码逻辑,确认无误后再用全部 300 行数据运行。这样可以快速定位错误,也减少大文件处理时的等待时间。
8.3 命名规范
DataFrame 列名如果是中文,尽量在读取后统一重命名为英文,避免后续代码中出现不必要的编码问题。
df.rename(columns={"订单号": "order_id", "商品ID": "product_id"}, inplace=True)统一使用df作为主 DataFrame 的变量名,不同阶段可以用df_clean、df_grouped等前缀标识状态,但不要一个脚本里出现十几个含义不清的名字。
8.4 可视化配置抽成公共函数
如果项目中有多张图表,中文字体设置、画布大小、颜色风格通常是一致的。可以把这些配置抽成一个函数或单独放到配置段:
import matplotlib.pyplot as plt def setup_chart_style(): plt.rcParams["font.sans-serif"] = ["SimHei"] plt.rcParams["axes.unicode_minus"] = False plt.rcParams["figure.dpi"] = 120调用这段配置后,所有图表统一使用同一套风格,避免每张图单独设置。
8.5 合理处理缺失值
删除缺失值不一定总是最优选择。如果某一列缺失比例超过 50%,直接删掉这一列可能更合理;如果只是个别行缺失,删除这些行即可;如果缺失值有一定规律,考虑用均值、中位数或前向填充补全。具体选择要根据业务场景判断。
8.6 数据量大时关注内存
当 DataFrame 达到几百万行时,内存占用会成为瓶颈。可以做三件事:
- 读取 CSV 时通过
usecols参数只读需要的列。 - 使用
dtypes调整数据类型,比如把int64转成int32。 - 处理完中间数据后及时删除不再使用的对象,释放内存。
9. 总结与下一步学习建议
回顾一下,这篇文章完成了几件事:
- 理清了 NumPy、Pandas、Matplotlib 三个库的定位和分工。
- 覆盖了 NumPy 的数组创建、切片、布尔筛选和统计计算。
- 覆盖了 Pandas 的 Series/DataFrame、数据读取、清洗、分组聚合和表合并。
- 覆盖了 Matplotlib 的折线图、柱状图、散点图、直方图、子图和中文字体配置。
- 通过一个电商销售分析案例,把三个库串成了完整工作流。
接下来如果想继续深入,可以按三个方向扩展:
方向一:数据分析深入。学习更复杂的数据变换方法,比如透视表pivot_table、时间序列处理、窗口函数。这些在 Pandas 官方文档中都有完整说明。
方向二:可视化进阶。学习更现代化的可视化库。Seaborn 基于 Matplotlib 封装了更多统计图表;Plotly 支持交互式图表,适合放到网页端展示;Pyecharts 适合中文环境下的业务报表。
方向三:实战项目积累。在 Kaggle、天池等平台找公开数据集,自己独立完成数据探索、清洗、分析和可视化报告。坚持做两三个完整的项目,对数据分析流程的理解会明显上台阶。
最后留一个练习任务:找一份你所在城市近一个月的天气数据,包含日期、最高温度、最低温度、天气状况四列,用 Pandas 读取数据,计算月均最高温和月均最低温,再用 Matplotlib 绘制一张温度变化折线图。做到这一步,你就已经把三件套的核心用法真正串起来了。
如果这篇文章对你有帮助,可以收藏备用,后续遇到数据分析相关的问题也能随时回来查阅。