系列文章

Python 从入门到精通

第 29 / 36 篇

从环境安装和基础语法出发,逐步学习工程实践、自动化、数据处理与 Web 开发。

  1. 01
    Python 怎么装、怎么用
  2. 02
    变量、数字和字符串
  3. 03
    列表:把一组数据放在一起
  4. 04
    元组、集合和字典
  5. 05
    条件判断:让程序做选择
  6. 06
    循环:重复的事交给程序
  7. 07
    函数:把代码整理成可复用的块
  8. 08
    模块与包:拆分你的程序
  9. 09
    输入、输出与字符串格式化
  10. 10
    文件读写:保存程序的数据
  11. 11
    异常处理:程序出错时怎么办
  12. 12
    基础阶段练习:命令行记账本
  13. 13
    类和对象:面向对象入门
  14. 14
    继承、组合与特殊方法
  15. 15
    迭代器与生成器
  16. 16
    列表推导式与生成器表达式
  17. 17
    装饰器:给函数增加能力
  18. 18
    上下文管理器与 with
  19. 19
    类型标注与 dataclass
  20. 20
    正则表达式:从文本中找规律
  21. 21
    日期、时间与时区
  22. 22
    日志与调试
  23. 23
    虚拟环境与依赖管理
  24. 24
    测试:让修改不再提心吊胆
  25. 25
    网络请求:用 Python 调用 API
  26. 26
    网页解析与合规采集
  27. 27
    操作 Excel、CSV 与批量文件
  28. 28
    SQLite:给程序加一个数据库
  29. 29
    数据分析入门:NumPy 与 Pandas正在阅读
  30. 30
    画图:把数据变得直观
  31. 31
    Flask 入门:做一个小网站
  32. 32
    异步编程:同时处理多项任务
  33. 33
    线程、进程与并发选择
  34. 34
    性能分析与优化
  35. 35
    项目结构、配置与发布
  36. 36
    综合项目:从需求到上线

查看整个系列 →

数据有了、也存进数据库了,接下来自然想:这些数据能告诉我什么?比如一年账单里吃饭花了多少、哪个月支出最高。数据分析的两大神器:NumPy(高效数值计算)和 Pandas(表格数据处理)。这一篇入门,够你用起来。

安装

pip install numpy pandas

NumPy:高效数组

NumPy 的核心是 ndarray(N 维数组),比 Python 列表快几十倍,尤其是数学运算:

import numpy as np

# 创建数组
arr = np.array([1, 2, 3, 4, 5])
print(arr)              # [1 2 3 4 5]
print(arr * 2)          # [ 2  4  6  8 10](向量化运算,不用循环!)
print(arr + 10)         # [11 12 13 14 15]
print(arr ** 2)         # [ 1  4  9 16 25]

# 对比列表:列表 * 2 是重复,数组 * 2 是每个元素乘 2
lst = [1, 2, 3]
print(lst * 2)          # [1, 2, 3, 1, 2, 3]

# 常用创建方式
print(np.arange(10))            # [0 1 2 ... 9](类似 range)
print(np.zeros(3))              # [0. 0. 0.]
print(np.ones((2, 3)))          # 2 行 3 列全 1
print(np.random.rand(3))        # 3 个随机数

# 统计
scores = np.array([88, 92, 76, 59, 100])
print(scores.mean())    # 83.0
print(scores.max())     # 100
print(scores.min())     # 59
print(scores.std())     # 标准差(波动程度)
print(scores.sum())     # 415

核心思想:对整个数组做运算,不用写循环——这叫向量化,又快又简洁。

Pandas:表格数据的主角

Pandas 两个核心结构:

  • Series:一列数据(带索引)
  • DataFrame:二维表格(多个 Series 组成),像 Excel 表
import pandas as pd

# 从字典创建 DataFrame
df = pd.DataFrame({
    "姓名": ["小明", "小红", "小刚", "小丽"],
    "城市": ["敦化", "延吉", "长春", "敦化"],
    "分数": [88, 92, 76, 95],
    "年龄": [18, 17, 19, 18],
})
print(df)
#    姓名  城市  分数  年龄
# 0  小明  敦化   88   18
# 1  小红  延吉   92   17
# 2  小刚  长春   76   19
# 3  小丽  敦化   95   18

读取数据

# 读 CSV(数据分析的入口,最常见)
df = pd.read_csv("sales.csv")
# 读 Excel
df = pd.read_excel("sales.xlsx")
# 读数据库
import sqlite3
conn = sqlite3.connect("ledger.db")
df = pd.read_sql_query("SELECT * FROM records", conn)

# 先看看数据长什么样
print(df.head())        # 前 5 行
print(df.info())        # 列名、类型、非空数量
print(df.describe())    # 数值列的统计摘要(均值、最大最小、分位数)

选择和筛选

# 选列
print(df["分数"])               # 一列(Series)
print(df[["姓名", "分数"]])      # 多列(DataFrame)

# 按条件筛选行(最常用!)
high = df[df["分数"] >= 90]
print(high)
#    姓名  城市  分数  年龄
# 1  小红  延吉   92   17
# 3  小丽  敦化   95   18

# 多条件:& 且、| 或
filtered = df[(df["分数"] >= 90) & (df["城市"] == "敦化")]
print(filtered)

# 排序
print(df.sort_values("分数", ascending=False))   # 按分数降序

# 取某几行
print(df.iloc[0])        # 第一行(按位置)
print(df.iloc[1:3])      # 第 2-3 行
print(df.loc[df["姓名"] == "小明"])   # 按条件定位

记住 df[条件] 就是筛选,条件是”对每一行判断真假”。多条件要加括号,用 &|(不是 and/or!)。

分组统计:groupby

这是数据分析最常用的操作——”按类别汇总”:

import pandas as pd

df = pd.DataFrame({
    "类别": ["吃饭", "交通", "吃饭", "购物", "交通", "吃饭"],
    "金额": [12.5, 5.0, 8.0, 99.0, 3.0, 15.0],
})

# 按类别分组求和
print(df.groupby("类别")["金额"].sum())
# 类别
# 交通     8.0
# 吃饭    35.5
# 购物    99.0

# 分组后多个统计
print(df.groupby("类别")["金额"].agg(["sum", "mean", "count"]))
#       sum   mean  count
# 类别
# 交通   8.0   4.00      2
# 吃饭  35.5  11.83      3
# 购物  99.0  99.00      1

# 实战:月消费报表
# df.groupby(df["日期"].str[:7])["金额"].sum()   # 按月份聚合

缺失值和清洗

真实数据永远有坑:缺值、重复、类型不对。

import pandas as pd

df = pd.DataFrame({"姓名": ["小明", None, "小刚"], "分数": [88, 92, None]})

# 看缺失
print(df.isnull())          # 每个位置是否缺失
print(df.isnull().sum())    # 每列缺失数量

# 处理缺失:删掉有缺失的行 / 填充
df_drop = df.dropna()               # 删缺失行(数据少时慎用)
df_fill = df.fillna({"姓名": "未知", "分数": 0})   # 按列填充

# 去重
df2 = df.drop_duplicates()

# 类型转换(读 CSV 时数字常变成字符串)
df["分数"] = pd.to_numeric(df["分数"], errors="coerce")   # 转数字,转不了的变 NaN

导出

df.to_csv("output.csv", index=False, encoding="utf-8-sig")   # Excel 打开不乱码
df.to_excel("output.xlsx", index=False)
# index=False:不把行号写进文件,99% 的情况都要加

新手坑

坑 1:筛选用 and/or 报错。DataFrame 筛选必须用 & | 且每个条件加括号——df[df.a > 1 and df.b < 2] 会报 ValueError。

坑 2:改副本不生效。df[df["分数"] > 90]["新列"] = 1 会警告(SettingWithCopyWarning),改的是副本。要用 df.loc[条件, "新列"] = 1

坑 3:中文乱码。导出 CSV 用 encoding="utf-8-sig"

小结

  • NumPy 数组:向量化运算(整个数组直接算),比列表快得多
  • Pandas 两个核心:Series(一列)、DataFrame(表格)
  • df[条件] 筛选行,多条件用 &/| 加括号
  • groupby("列")["数值列"].sum() 分组统计,报表神器
  • 清洗:isnull 查缺失、dropna/fillna 处理、drop_duplicates 去重
  • 导出加 index=False,CSV 用 utf-8-sig

练习

  1. 用 pandas 读一个 CSV(可自己造),按类别分组统计金额,找出花最多的类别
  2. 给 DataFrame 加一列”是否及格”(分数 >= 60 为 True)
  3. 思考:df[df["分数"] > 90] 里的条件到底返回了什么?为什么它能当”筛选器”用?提示:打印一下 df["分数"] > 90 看看