Python 数据分析学习笔记
基于 pandas 官方文档及当前项目 Demo 代码总结,涵盖 NumPy、Pandas、Matplotlib 三大核心库。
目录
一、NumPy 基础
NumPy 是 Python 科学计算的基础库,核心是 ndarray(N 维数组)。
1.1 数组创建
import numpy as np
# 从列表创建
arr = np.array([1, 2, 3, 4])
arr2d = np.array([[1, 2], [3, 4]])
# 特殊数组
np.zeros((3, 4)) # 全 0 数组,shape=(3,4)
np.ones((2, 3)) # 全 1 数组
np.full((2, 2), 7.5) # 填充指定值
np.eye(3) # 3x3 单位矩阵
np.empty((2, 3)) # 未初始化数组(值随机)
# 序列生成
np.arange(0, 10, 2) # [0, 2, 4, 6, 8],类似 range()
np.linspace(0, 1, 5) # [0.0, 0.25, 0.5, 0.75, 1.0],等间距 5 个点
1.2 数组属性
arr.shape # 形状元组,如 (3, 5)
arr.ndim # 维度数
arr.dtype # 元素数据类型,如 int64、float64
arr.size # 元素总数
1.3 索引与切片
arr[2:5] # 基本切片(视图,共享内存)
arr[:, 1:3] # 二维:所有行的第 1-2 列
arr[arr > 5] # 布尔索引,返回满足条件的一维数组
1.4 聚合函数
np.sum(arr, axis=0) # axis=0 列求和,axis=1 行求和
np.mean(arr) # 平均值
np.std(arr) # 标准差
np.min(arr) / np.max(arr)
np.argmin(arr) / np.argmax(arr) # 最值位置
1.5 广播机制(Broadcasting)
不同形状的数组在进行运算时会自动扩展维度:
arr = np.array([[1, 2, 3], [4, 5, 6]]) # shape (2, 3)
arr + 10 # 标量广播到每个元素
arr + np.array([1, 2, 3]) # 形状 (3,) 广播到 (2, 3)
1.6 随机数生成
rng = np.random.default_rng(seed=42) # 推荐方式(可复现)
rng.random((2, 3)) # [0, 1) 均匀分布
rng.standard_normal((3, 4)) # 标准正态分布
rng.integers(0, 10, size=5) # 随机整数
# 旧版 API(不推荐)
# np.random.rand(3, 2)
# np.random.seed(42)
二、Pandas 基础
2.1 核心数据结构
DataFrame(二维表格)
import pandas as pd
df = pd.DataFrame({
"Name": ["Braund, Mr. Owen Harris", "Allen, Mr. William Henry"],
"Age": [22, 35],
"Sex": ["male", "male"],
})
print(df)
Series(单列数据)
ages = pd.Series([22, 11, 23], name="Age")
print(ages)
2.2 数据读写(I/O)
# CSV 读入
titanic = pd.read_csv("data/titanic.csv")
# CSV 写出
titanic.to_csv("output.csv", index=False)
# Excel 读写
titanic.to_excel("titanic.xlsx", sheet_name="passengers", index=False)
df = pd.read_excel("titanic.xlsx", sheet_name="passengers")
常用参数:
| 参数 | 说明 |
|---|---|
sep=',' |
分隔符(如 '\t' 用于 TSV) |
header=0 |
列名所在行,None 表示无列名 |
index_col=0 |
指定某列为行索引 |
parse_dates=True |
自动解析日期列 |
2.3 数据查看与检查
df.head(8) # 查看前 N 行(默认 5)
df.tail(10) # 查看后 N 行
df.dtypes # 各列数据类型
df.info() # 技术摘要:行数、列数、数据类型、内存、非空数
df.shape # 元组 (行数, 列数)
df.describe() # 数值列的统计信息:count、mean、std、min、25%、50%、75%、max
注意: describe() 默认只统计数值列,文本列会被自动忽略。
2.4 数据筛选与索引
选择列
titanic["Age"] # 返回 Series
titanic[["Age", "Fare"]] # 返回 DataFrame
条件过滤(布尔索引)
# 单条件
above = titanic[titanic["Age"] > 35]
# 多条件:使用 &(与)、|(或)、~(非)
class_23 = titanic[titanic["Pclass"].isin([2, 3])]
# 非空筛选
age_no_na = titanic[titanic["Age"].notna()]
loc:标签索引(左闭右闭)
adult_names = titanic.loc[titanic["Age"] > 35, "Name"] # 条件 + 指定列
titanic.loc[0:5, ["Name", "Age"]] # 行切片(含5)+ 指定列
iloc:位置索引(左闭右开)
titanic.iloc[9:25, 2:5] # 第 9-24 行,第 2-4 列
titanic.iloc[0:3, 3] = "wsj" # 赋值
2.5 聚合与分组
基本统计
titanic["Age"].mean() # 平均值
titanic[["Age", "Fare"]].median() # 中位数
titanic["Age"].min() / .max() / .std() # 最小值 / 最大值 / 标准差
agg:自定义多指标聚合
titanic.agg({
"Age": ["min", "max", "median", "skew"],
"Fare": ["min", "max", "median", "mean"],
})
groupby:分组聚合
# 按性别分组,计算均值
titanic[["Sex", "Age"]].groupby("Sex").mean()
# 在分组数据上选择列
titanic.groupby("Sex")["Age"].mean()
# 多列分组
titanic.groupby(["Sex", "Pclass"])["Fare"].mean()
# 计算每个组的记录数
titanic.groupby("Pclass")["Pclass"].count()
value_counts:计数
titanic["Pclass"].value_counts() # 每个类别的出现次数
2.6 排序
# 单列排序
titanic.sort_values(by="Age")
# 多列排序(先按 Pclass 降序,再按 Age 降序)
titanic.sort_values(by=["Pclass", "Age"], ascending=False)
2.7 数据重塑(长宽表转换)
长表 → 宽表:pivot
# 将每个 location 的值作为一列展示
no2.pivot(columns="location", values="value")
index:指定行索引(默认使用原始 index)columns:指定哪一列的值成为新列名values:指定填充到新列的数据
数据透视表:pivot_table
pivot_table 与 pivot 类似,但当有重复行时,会使用聚合函数合并:
air_quality.pivot_table(
values="value",
index="location",
columns="parameter",
aggfunc="mean", # 聚合函数
margins=True, # 添加行列汇总
)
宽表 → 长表:melt
no2_pivoted.melt(id_vars="date.utc")
# 详细参数
no2_pivoted.melt(
id_vars="date.utc", # 保留的标识列
value_vars=["BETR801", "FR04014"], # 需要融化的列
value_name="NO_2", # 值列的新列名(默认"value")
var_name="id_location", # 原列名列的新列名(默认"variable")
)
2.8 多表合并
concat:轴向拼接
# axis=0:纵向(行)拼接(上下堆叠)
air_quality = pd.concat([air_quality_pm25, air_quality_no2], axis=0)
# axis=1:横向(列)拼接
merge:数据库风格连接
# 内连接(默认):只保留两表共有的键
pd.merge(left_df, right_df, on="location")
# 左连接:保留左表所有行,右表匹配不到的填 NaN
pd.merge(air_quality, stations_coord, how="left", on="location")
# 两表列名不同时
pd.merge(air_quality, parameters_df,
how="left", left_on="parameter", right_on="id")
| how 选项 | 说明 |
|---|---|
'inner' |
内连接(默认),取交集 |
'left' |
左连接,保留左表所有行 |
'right' |
右连接,保留右表所有行 |
'outer' |
外连接,取并集 |
2.9 时间序列
转换为日期时间
air_quality["datetime"] = pd.to_datetime(air_quality["datetime"])
dt 访问器:提取日期组件
air_quality["datetime"].dt.month # 月份
air_quality["datetime"].dt.hour # 小时
air_quality["datetime"].dt.weekday # 星期几(0=周一)
air_quality["datetime"].dt.year # 年份
air_quality["datetime"].dt.day # 日
按时间分组聚合
# 按星期几 + 地点分组求均值
air_quality.groupby(
[air_quality["datetime"].dt.weekday, "location"]
)["value"].mean()
# 按每天的小时分组
air_quality.groupby(
[air_quality["datetime"].dt.hour]
)["value"].mean().plot(kind="bar", rot=0)
日期时间作为索引
no_2 = air_quality.pivot(index="datetime", columns="location", values="value")
# 通过索引切片选择时间范围
no_2["2019-05-20":"2019-05-21"].plot()
重采样 resample
no_2.resample("MS").max() # 每月最大值(MS = Month Start)
no_2.resample("D").mean() # 每日均值(D = Day)
常用频率别名:
| 别名 | 说明 | 别名 | 说明 |
|---|---|---|---|
'D' |
日历日 | 'H' |
小时 |
'W' |
周 | 'T' / 'min' |
分钟 |
'MS' |
月起始 | 'QS' |
季度起始 |
'M' |
月末 | 'YS' / 'AS' |
年起始 |
2.10 文本处理
通过 .str 访问器操作字符串列:
titanic["Name"].str.lower() # 转小写
titanic["Name"].str.split(",") # 按分隔符拆分
titanic["Name"].str.contains("Mr") # 是否包含子串
titanic["Name"].str.replace("Mr", "Mister") # 替换
titanic["Name"].str.len() # 字符串长度
titanic["Name"].str.strip() # 去首尾空白
2.11 列操作与重命名
新增/计算列
# 新增计算列(单位转换:mg/m³ → µg/m³)
air_quality["london_mg_per_cubic"] = air_quality["station_london"] * 1.882
rename:重命名
air_quality.rename(columns={
"station_antwerp": "BETR801",
"station_paris": "FR04014",
"station_london": "London Westminster",
})
三、可视化图表(Matplotlib + Pandas Plot)
3.1 Pandas 内置绘图(快速探索)
Pandas 的 plot() 方法是 Matplotlib 的包装,适合快速数据探索:
import matplotlib.pyplot as plt
# 全部列折线图
air_quality.plot()
plt.show()
# 单列折线图
air_quality["station_paris"].plot()
plt.show()
支持的图表类型
df.plot() # 折线图(默认)
df.plot.scatter(x, y) # 散点图
df.plot(kind="scatter", x="col1", y="col2", alpha=0.5)
df.plot.box() # 箱线图
df.plot.bar() # 柱状图
# 或 df.plot(kind="bar", rot=0)
df.plot.area(figsize=(12, 4), subplots=True) # 面积图(可分面子图)
df.plot.hist() # 直方图
3.2 Matplotlib 显式接口(推荐,更灵活)
Figure/Axes 模型
# 创建画布和坐标区
fig, axs = plt.subplots(figsize=(12, 4))
# 在坐标区上绘图
air_quality.plot.area(ax=axs)
axs.set_ylabel("NO$_2$ concentration")
axs.set_title("Air Quality Over Time")
# 保存
fig.savefig("no2_concentrations.png")
plt.show()
常用图表类型
# 折线图
ax.plot(x, y, 'o-', label="Series 1")
# 散点图
ax.scatter(x, y, s=size, c=color, alpha=0.5)
# 柱状图
ax.bar(x, height, width=0.8)
# 箱线图
ax.boxplot(data)
# 直方图
ax.hist(x, bins=50, alpha=0.75)
格式化字符串
fmt = '[marker][line][color]'
- 标记(marker):
'o'圆,'^'三角,'s'方形,'D'菱形,'*'星 - 线型(line):
'-'实线,'--'虚线,':'点线,'-.'点划线 - 颜色(color):
'b'蓝,'r'红,'g'绿,'k'黑,'m'品红,'y'黄
示例:'ro' 红色圆点, '--g' 绿色虚线, '^k:' 黑三角+点线
自定义设置
ax.set_xlabel("X Label")
ax.set_ylabel("Y Label")
ax.set_title("Title", fontsize=14)
ax.legend(loc='best') # 图例位置:'upper right', 'upper left', 'lower left', 'center', 'best'
ax.set_xlim(0, 100) # X 轴范围
ax.set_ylim(0, 100) # Y 轴范围
ax.grid(True) # 显示网格
多子图
# 创建 2x2 子图网格
fig, axs = plt.subplots(2, 2, figsize=(12, 8))
axs[0, 0].plot(x1, y1)
axs[0, 1].scatter(x2, y2)
axs[1, 0].bar(x3, y3)
axs[1, 1].hist(data)
fig.tight_layout() # 自动调整间距
3.3 保存图表
# 从 pyplot 保存
plt.savefig("figure.png", dpi=150, bbox_inches="tight")
# 从 Figure 对象保存
fig.savefig("figure.png", dpi=200, transparent=True)
支持的格式:png、pdf、svg、jpg 等。
附录:常用速查表
Pandas 数据查看
| 方法 | 作用 |
|---|---|
df.head(n) / df.tail(n) |
前/后 N 行 |
df.dtypes |
列数据类型 |
df.info() |
数据结构摘要 |
df.describe() |
数值统计信息 |
df.shape |
(行数, 列数) |
df.columns |
列名列表 |
Pandas 选择数据
| 方式 | 语法 |
|---|---|
| 单列 | df["col"] |
| 多列 | df[["col1", "col2"]] |
| 条件行 | df[df["col"] > 10] |
| 标签索引 | df.loc[row, col] |
| 位置索引 | df.iloc[row, col] |
Pandas 数据处理
| 操作 | 方法 |
|---|---|
| 排序 | df.sort_values(by="col") |
| 分组 | df.groupby("col")["target"].mean() |
| 聚合 | df.agg({"col": ["min", "max"]}) |
| 长转宽 | df.pivot(columns="col", values="val") |
| 宽转长 | df.melt(id_vars="col") |
| 拼接 | pd.concat([df1, df2], axis=0) |
| 连接 | pd.merge(df1, df2, on="key", how="left") |
| 重命名 | df.rename(columns={"old": "new"}) |
| 新建列 | df["new_col"] = df["col"] * 2 |
Matplotlib 图表选择指南
| 数据类型 | 推荐图表 | 方法 |
|---|---|---|
| 时间序列趋势 | 折线图 | plot() |
| 两个数值变量关系 | 散点图 | plot.scatter() / scatter() |
| 分类比较 | 柱状图 | plot.bar() / bar() |
| 分布查看 | 直方图 / 箱线图 | hist() / box() |
| 占比/累计 | 面积图 | area() |
注:本笔记示例代码源自 _E:\PythonProject1\_ 项目中的 _pandas.demo.py_ ~ _pandas8-demo.py_,结合 pandas、NumPy、Matplotlib 官方文档整理。
相关条目
- python
- 集合