强曰为道

与天地相似,故不违。知周乎万物,而道济天下,故不过。旁行而不流,乐天知命,故不忧.
文档目录

19 - 数据科学

第 19 章:数据科学

掌握 NumPy、Pandas、Matplotlib 和 Jupyter 进行数据处理与分析。


19.1 Jupyter Notebook

19.1.1 使用 Jupyter

# 安装
$ pip install jupyterlab

# 启动
$ jupyter lab
# 浏览器打开 http://localhost:8888

# 或使用 VS Code 的 Jupyter 扩展

Jupyter 支持交互式编程,混合代码、文本、图表,非常适合数据分析和探索。

19.1.2 Jupyter 基本操作

快捷键功能
Shift+Enter运行当前单元格
Esc+A上方插入单元格
Esc+B下方插入单元格
Esc+M转为 Markdown
Esc+DD删除单元格

19.2 NumPy

19.2.1 数组创建

import numpy as np

# 从列表创建
arr = np.array([1, 2, 3, 4, 5])
print(type(arr))  # <class 'numpy.ndarray'>

# 常用创建方法
np.zeros(5)              # [0. 0. 0. 0. 0.]
np.ones((3, 4))          # 3x4 全1矩阵
np.arange(0, 10, 2)      # [0, 2, 4, 6, 8]
np.linspace(0, 1, 5)     # [0.   0.25 0.5  0.75 1.  ]
np.random.rand(3, 3)     # 3x3 随机矩阵
np.eye(3)                # 3x3 单位矩阵

19.2.2 数组操作

import numpy as np

arr = np.array([[1, 2, 3], [4, 5, 6]])

print(arr.shape)      # (2, 3)
print(arr.ndim)       # 2
print(arr.size)       # 6
print(arr.dtype)      # int64

# 索引和切片
print(arr[0, 1])      # 2
print(arr[:, 0])      # [1, 4] 第一列
print(arr[1, :])      # [4, 5, 6] 第二行

# 变形
arr.reshape(3, 2)     # 变形
arr.flatten()         # 展平

# 转置
arr.T                 # 转置

19.2.3 数学运算

import numpy as np

a = np.array([1, 2, 3])
b = np.array([4, 5, 6])

# 逐元素运算
print(a + b)          # [5, 7, 9]
print(a * b)          # [4, 10, 18]
print(a ** 2)         # [1, 4, 9]

# 聚合
print(np.sum(a))      # 6
print(np.mean(a))     # 2.0
print(np.std(a))      # 标准差
print(np.max(a))      # 3
print(np.dot(a, b))   # 点积: 32

# 矩阵运算
A = np.array([[1, 2], [3, 4]])
B = np.array([[5, 6], [7, 8]])
print(A @ B)          # 矩阵乘法
print(np.linalg.inv(A))  # 逆矩阵

19.2.4 广播(Broadcasting)

# 形状不同的数组也能运算
arr = np.array([[1, 2, 3], [4, 5, 6]])  # (2, 3)
scalar = 10
print(arr + scalar)   # 每个元素加 10

row = np.array([10, 20, 30])  # (3,)
print(arr + row)      # 每行加 row

19.3 Pandas

19.3.1 DataFrame 基础

import pandas as pd

# 创建 DataFrame
data = {
    "name": ["Alice", "Bob", "Charlie"],
    "age": [30, 25, 35],
    "city": ["北京", "上海", "广州"],
}
df = pd.DataFrame(data)
print(df)

#       name  age city
# 0    Alice   30   北京
# 1      Bob   25   上海
# 2  Charlie   35   广州

# 基本信息
print(df.shape)        # (3, 3)
print(df.dtypes)       # 数据类型
print(df.describe())   # 统计摘要
print(df.head(2))      # 前 2 行
print(df.tail(1))      # 最后 1 行

19.3.2 数据选择

# 列选择
df["name"]                 # 单列(Series)
df[["name", "age"]]        # 多列(DataFrame)

# 行选择
df.iloc[0]                 # 按位置
df.iloc[0:2]               # 切片
df.loc[0]                  # 按标签

# 条件筛选
df[df["age"] > 25]
df.query("age > 25")
df[df["city"].isin(["北京", "上海"])]

19.3.3 数据处理

# 添加列
df["salary"] = [20000, 15000, 25000]

# 删除列
df.drop(columns=["salary"], inplace=True)

# 排序
df.sort_values("age", ascending=False)

# 分组聚合
df.groupby("city")["age"].mean()

# 缺失值
df.isna()              # 检查缺失
df.fillna(0)           # 填充缺失
df.dropna()            # 删除缺失行

# 去重
df.drop_duplicates()

# 应用函数
df["age_group"] = df["age"].apply(lambda x: "青年" if x < 30 else "中年")

19.3.4 读写数据

# CSV
df = pd.read_csv("data.csv")
df.to_csv("output.csv", index=False, encoding="utf-8-sig")

# Excel
df = pd.read_excel("data.xlsx", sheet_name="Sheet1")
df.to_excel("output.xlsx", index=False)

# JSON
df = pd.read_json("data.json")
df.to_json("output.json", orient="records", force_ascii=False)

# 数据库
from sqlalchemy import create_engine
engine = create_engine("sqlite:///app.db")
df = pd.read_sql("SELECT * FROM users", engine)
df.to_sql("users", engine, if_exists="append", index=False)

19.4 Matplotlib

19.4.1 基本图表

import matplotlib.pyplot as plt
import numpy as np

# 折线图
x = np.linspace(0, 10, 100)
plt.figure(figsize=(10, 6))
plt.plot(x, np.sin(x), label="sin(x)")
plt.plot(x, np.cos(x), label="cos(x)")
plt.xlabel("x")
plt.ylabel("y")
plt.title("三角函数")
plt.legend()
plt.grid(True)
plt.savefig("trig.png", dpi=150, bbox_inches="tight")
plt.show()

19.4.2 常用图表类型

# 柱状图
categories = ["Python", "Java", "C++", "Go"]
values = [45, 30, 15, 10]
plt.bar(categories, values, color=["#3776AB", "#F89820", "#00599C", "#00ADD8"])

# 饼图
plt.pie(values, labels=categories, autopct="%1.1f%%")

# 散点图
x = np.random.randn(100)
y = x * 2 + np.random.randn(100) * 0.5
plt.scatter(x, y, alpha=0.6)

# 直方图
data = np.random.randn(1000)
plt.hist(data, bins=30, edgecolor="black")

19.4.3 Pandas 内置绘图

df = pd.DataFrame({
    "月份": ["1月", "2月", "3月", "4月"],
    "销售额": [100, 120, 115, 140],
    "利润": [20, 25, 22, 30],
})

df.plot(x="月份", y=["销售额", "利润"], kind="bar", figsize=(10, 6))
plt.savefig("sales.png")

19.5 数据处理实战

import pandas as pd
import numpy as np

# 加载数据
df = pd.read_csv("sales.csv")

# 数据清洗
df = df.dropna(subset=["amount"])
df["date"] = pd.to_datetime(df["date"])
df["amount"] = df["amount"].astype(float)

# 特征工程
df["year"] = df["date"].dt.year
df["month"] = df["date"].dt.month
df["weekday"] = df["date"].dt.day_name()

# 分析
monthly = df.groupby("month")["amount"].agg(["sum", "mean", "count"])
monthly.columns = ["总销售额", "平均订单额", "订单数"]

# 导出
monthly.to_excel("monthly_report.xlsx")
print(monthly)

19.6 注意事项

🔴 注意

  • 大数据集避免用 Python 循环,使用 NumPy/Pandas 向量化操作
  • Pandas 的 SettingWithCopyWarning 提醒链式赋值问题
  • Matplotlib 中文显示需要配置字体
  • Jupyter Notebook 不适合生产代码,适合探索分析

💡 提示

  • 使用 df.info()df.describe() 快速了解数据
  • 使用 df.query() 替代复杂的布尔索引
  • 使用 seabornplotly 创建更美观的图表
  • 大数据考虑使用 Polars 替代 Pandas

📌 业务场景

import pandas as pd

def generate_sales_report(csv_path: str, output_path: str):
    """生成销售报告。"""
    df = pd.read_csv(csv_path, parse_dates=["date"])

    # 按产品和月份汇总
    summary = df.groupby([df["date"].dt.to_period("M"), "product"]).agg(
        total_sales=("amount", "sum"),
        order_count=("amount", "count"),
        avg_order=("amount", "mean"),
    ).round(2)

    # 导出
    with pd.ExcelWriter(output_path) as writer:
        summary.to_excel(writer, sheet_name="汇总")
        df.pivot_table(values="amount", index="product", columns=df["date"].dt.month, aggfunc="sum").to_excel(writer, sheet_name="产品-月份")

    print(f"报告已生成: {output_path}")

19.7 扩展阅读