Python_Jupyther
Python_Jupyther
一、Ndarray
1. ndarray的特性
1.1 多维性
例题 1:
-
代码
import numpy as np arr = np.array(5) print(arr) print(f"arr的维度是:{arr.ndim}") #维度 -
结果
5 arr的维度是:0
例题 2:
-
代码
import numpy as np arr = np.array([1, 2, 3, 4]) print(arr) print(f"arr的维度是:{arr.ndim}") #维度 -
结果
[1 2 3 4] arr的维度是:1
例题 3:
-
代码
import numpy as np arr = np.array([[1, 2, 3], [4, 5, 6]]) print(arr) print(f"arr的维度是:{arr.ndim}") #维度 -
结果
[[1 2 3] [4 5 6]] arr的维度是:2
1.2 同质性
例题:
-
代码
arr = np.array([1, 2, "hello"]) print(arr) type(arr)
-
结果
['1' '2' 'hello'] numpy.ndarray
-
什么是同质性? ✅ NumPy 数组必须满足:整个数组里所有元素,只能是同一种数据类型 ❌ 不能像 Python 列表一样:同时存 int、str、float、bool 随意混搭
-
类型强制转换规则 当你放入多种不同类型数据时,numpy 会自动向上强制统一类型, 优先级:字符串(str)>浮点数(float)>整数(int)
-
2. ndarray的属性
| 属性名称 | 通俗解释 | 使用示例 |
|---|---|---|
| shape | 数组的形状:行数和列数(或更高维度的尺寸)。 | arr.shape |
| ndim | 维度数量:数组是几维的(1维、2维等)。 | arr.ndim |
| size | 总元素个数:数组中所有元素的总数。 | arr.size |
| dtype | 元素类型:数组中元素的类型(整数、浮点数等)。 | arr.dtype |
| T | 转置:行变列,列变行。 | arr.T |
| itemsize | 单个元素占用的内存字节数。 | arr.itemsize |
| nbytes | 数组总内存的占用量:size*itemsize。 | arr.nbytes |
| flags | 内存存储方式:是否连续存储(高级优化)。 | arr.flags |
例题 1:
-
代码
import numpy as np arr = np.array(5) print(arr) print(f"arr的形状是:{arr.shape}") #形状 print(f"arr的维度是:{arr.ndim}") #维度 print(f"arr的元素个数是:{arr.size}") #元素个数 print(f"arr的元素数据类型是:{arr.dtype}") #元素类型 -
结果
arr的形状是:() arr的维度是:0 arr的元素个数是:1 arr的元素数据类型是:int64
例题 2:
-
代码
import numpy as np arr = np.array([1, 2, 3, 4]) print(arr) print(f"arr的形状是:{arr.shape}") #形状 print(f"arr的维度是:{arr.ndim}") #维度 print(f"arr的元素个数是:{arr.size}") #元素个数 print(f"arr的元素数据类型是:{arr.dtype}") #元素类型 -
结果
[1 2 3 4] arr的形状是:(4,) arr的维度是:1 arr的元素个数是:4 arr的元素数据类型是:int64
例题 3:
-
代码
import numpy as np arr = np.array([[1, 2, 3], [4, 5, 6]]) print(arr) print(f"arr的形状是:{arr.shape}") #形状 print(f"arr的维度是:{arr.ndim}") #维度 print(f"arr的元素个数是:{arr.size}") #元素个数 print(f"arr的元素数据类型是:{arr.dtype}") #元素类型 print(f"arr的转置是:\n{arr.T}") -
结果
[[1 2 3] [4 5 6]] arr的形状是:(2, 3) arr的维度是:2 arr的元素个数是:6 arr的元素数据类型是:int64 arr的转置是: [[1 4] [2 5] [3 6]]
例题 4:
-
代码
import numpy as np arr = np.array([1, 2, 2.5]) print(arr) print(f"arr的形状是:{arr.shape}") #形状 print(f"arr的维度是:{arr.ndim}") #维度 print(f"arr的元素个数是:{arr.size}") #元素个数 print(f"arr的元素数据类型是:{arr.dtype}") #元素类型 print(f"arr的转置是:\n{arr.T}") -
结果
[1. 2. 2.5] arr的形状是:(3,) arr的维度是:1 arr的元素个数是:3 arr的元素数据类型是:float64 arr的转置是: [1. 2. 2.5]
3. ndarray的创建
| 用途 | 方法 | |||
|---|---|---|---|---|
| 基础构造 | np.array() | np.copy() | ||
| 预定义形状填充 | np.zeros() | np.ones() | np.empty() | np.full() |
| 基于数值范围生成 | np.arange() | np.linspace() | np.logspace() | |
| 特殊矩阵生成 | np.eye() | np.diag() | ||
| 随机数组生成 | np.random.rand() | np.random.randn() | np.random.randint() | |
| 高级构造方法 | np.array() | np.loadtxt() | np.fromfunction() |
3.1 基础构造
例题 1: np.array()
-
代码
np.array()
# np.array() arr = np.array([1, 2, 3, 4]) print(arr.ndim) print(arr)
-
结果
1 [1 2 3 4]
例题 2: np.copy()
np.copy()
-
代码
# np.copy() arr = np.array([1, 2, 3, 4]) arr1 = np.copy(arr)# 元素跟原始数组一致,但是两个数组是两个对象 print(f"修改前的arr1: {arr1}") arr[0] = 5 print(f"修改后的arr1: {arr1}") print(f"修改后的arr: {arr}") -
结果
修改前的arr1: [1 2 3 4] 修改后的arr1: [1 2 3 4] 修改后的arr: [5 2 3 4]
3.2 预定义形状填充
例题 1: np.zeros()
全0 np.zeros()
-
代码
# 全0 arr = np.zeros((2, 3)) print(arr) print(arr.dtype) # 去掉数组中的. arr = np.zeros((2, 3), dtype=int) print(arr) print(arr.dtype)
-
结果
[[0. 0. 0.] [0. 0. 0.]] float64 [[0 0 0] [0 0 0]] int64
例题 2: np.ones()
全1 np.ones()
-
代码
# 全1 np.ones() arr = np.ones((2, 3),dtype= int) print(arr) print(arr.dtype)
-
结果
[[1 1 1] [1 1 1]] int64
例题 3: np.empty()
np.empty()
-
代码
# 未初始化 arr = np.empty((4, 3)) print(arr) print(arr.dtype)
-
结果
未初始化值,导致每一次运行结果都不相同,随机数 数组里的值是内存里原来残留的随机垃圾值
[[8.65564892e-312 2.47032823e-322 0.00000000e+000] [0.00000000e+000 1.24610723e-306 2.42336543e-057] [4.26803049e-090 6.70370895e+170 1.26071062e-076] [2.80595484e-032 3.99910963e+252 7.91880668e+165]] float64
例题 4: np.full()
填充 np.full()
-
代码
# 填充 arr = np.full((3, 4), 2026) print(arr) print(arr.dtype)
-
结果
[[2026 2026 2026 2026] [2026 2026 2026 2026] [2026 2026 2026 2026]] int64
例题 5: 相似数组
-
代码
# 相似数组 arr1 = np.zeros_like(arr) print(arr1) arr2 = np.full_like(arr,6) print(arr2)
-
结果
最关键的 3 个特点(必考)
-
形状完全相同(几行几列一模一样)
-
数据类型完全相同(float 还是 float,int 还是 int)
-
只有数值变了(0 / 自定义值)
[[0 0 0 0] [0 0 0 0] [0 0 0 0]] [[6 6 6 6] [6 6 6 6] [6 6 6 6]]
-
3.3 基于数值范围生成
例题 1: np.arange()
-
代码
# 等差数列 2 4 6 8 arr = np.arange(2, 10, 2) print(arr)
-
结果
[2 4 6 8]
例题 2: np.linspace()
-
代码
# 等间隔数列 arr = np.linspace(0, 100, 5, dtype=int) #【0,100】等分5份 print(arr) arr1 = np.arange(0,101,25) print(arr1)
-
结果
[ 0 25 50 75 100] [ 0 25 50 75 100]
例题 3: np.logspace()
-
代码
# 对数间隔 arr = np.logspace(0, 4, 2, base=2) # 结果: [1.0, 16.0] → 2^0=1, 2^4=16 print(arr) arr1 = np.logspace(0, 4, 3, base=2) # 结果: [1.0, 4.0, 16.0] → 2^0=1, 2^2=4, 2^4=16 print(arr1)
-
结果
np.logspace( start, stop, num, base ) = 生成数组:base ^ start , base ^... , base ^ stop start:指数的起始值 stop:指数的结束值 num:要生成多少个数(间隔) base:底数(默认 10,这里用了 2)
[ 1. 16.] [ 1. 4. 16.]
3.4 特殊矩阵生成
例题 1: np.eye()
单位矩阵:np.eye()
-
代码
# 单位矩阵:单位矩阵的元素对角线上的元素为1,其他元素为0。 arr = np.eye(3,dtype= int) print(arr)
-
结果
[[1 0 0] [0 1 0] [0 0 1]]
例题 2: np.diag()
对角矩阵:np.diag()
-
代码
# 对角矩阵:对角矩阵的元素主对角线上的元素为非零,其他元素为0。 arr = np.diag([1, 2, 3]) print(arr)
-
结果
[[1 0 0] [0 2 0] [0 0 3]]
3.5 随机数组生成
例题 1: np.random.rand()
np.random.rand(a, b)→ 生成 a 行 b 列 的随机数组数值范围:[0, 1)→ 大于等于 0,小于 1
类型:浮点数 float
每次运行结果都不同(真随机)
-
代码
import numpy as np import random # 生成0-1的随机浮点数的2行3列数组 arr = np.random.rand(2, 3) print(arr)
-
结果
[[0.46840581 0.62238277 0.52689151] [0.47318083 0.14626589 0.18728893]]
例题 2: np.random.uniform()
np.random.uniform(最小值, 最大值, 形状)作用:生成指定区间内的均匀分布随机浮点数
uniform = 均匀分布:每个数字出现概率一样
范围 [low, high):包含 5,不包含 6
(2,3) = 2 行 3 列:想生成几维数组就写几
-
代码
# 生成指定区间的随机浮点数 arr = np.random.uniform(5, 6, (2, 3)) print(arr)
-
结果
[[5.49277557 5.66672825 5.72552547] [5.10512647 5.80878168 5.69181701]]
例题 3: np.random.randn()
数据特点:服从标准正态分布的随机浮点数 什么是标准正态分布?
平均值(均值)= 0
标准差 = 1
分布规律:
大部分数字集中在 0 附近
离 0 越远,数字出现的概率越小
可正、可负
取值范围:理论上无上下限,但绝大多数值在 [-3, 3] 之间
-
代码
# 生成随机数列(正态分布) # 两边小,中间大 import numpy as np arr = np.random.randn(2, 3) print(arr)
-
结果
[[ 0.32984444 0.40897001 0.26467712] [-0.29087049 0.9014669 -0.33968636]]
例题 4: np.random.randint()
1. randint 是左闭右开 [a, b)
randint(a, b)→ 包含 a,不包含 brandint(5, 10)→ 5 ~ 9 2. 第三个参数是数组形状(2, 3)→ 2 行 3 列(5,)→ 1 行 5 列()→ 单个数字 3. 生成的是整数 int
-
代码
# 生成指定区间的随机整数 import numpy as np arr = np.random.randint(5, 10, (2, 3)) print(arr)
-
结果
[[6 8 7] [5 5 7]]
例题 5: np.random.seed()
np.random.seed(42)作用:固定随机种子
只要种子数字一样,每次生成的随机数都完全相同
42 只是一个随便选的数字(可以换成 0、1、100 都行)
目的:让随机结果可复现
np.random.randint(1, 10, (2, 3))作用:生成指定范围的随机整数
最小值:
1(包含)最大值:
10(不包含,实际最大是 9)形状:
(2, 3)→ 2 行 3 列
-
代码
# 设置随机数种子:是用来初始化随机数生成器的一个值,它的作用是让随机数可重复 # 使用相同种子 -> 结果可重复 np.random.seed(42) arr = np.random.randint(1, 10, (2, 3)) print(arr)
-
结果
[[7 4 8] [5 7 3]]
例题6:random.random()
生成 [0.0, 1.0) 之间的随机浮点数
-
代码
import random print(random.random()) # 例如: 0.3745401188473625
例题7: random.uniform(a, b)
生成 [a, b] 之间的随机浮点数(包含两端)
-
代码
import random print(random.uniform(1.5, 10.5)) # 例如: 7.23456789
例题8: random.randint(a, b)
生成 [a, b] 之间的随机整数(包含两端)
-
代码
import random print(random.randint(1, 10)) # 例如: 7
4. ndarray的数据类型
| 说明 | 数据类型 |
|---|---|
| 布尔类型 | bool |
| 整数类型 | int 、 uint |
| 浮点数 | float |
| 复数 | complex |
-
代码
import numpy as np arr1 = np.array([1, 0, 3, 0], dtype=np.bool) print(f"arr1: {arr1}") arr2 = np.array([1, 0, 3, 0], dtype=np.int8) print(f"arr2: {arr2}") arr3 = np.array([1, 0, 3.6, 0], dtype=np.float32) print(f"arr3: {arr3}") -
结果
arr1: [ True False True False] arr2: [1 0 3 0] arr3: [1. 0. 3.6 0. ]
5. 索引与切片
5.1 一维数组的索引与切片
-
普通索引:获取单个元素
-
代码
import numpy as np arr = np.random.randint(1,100,15) print(arr) print(f"arr[10]: {arr[10]}")-
结果
[40 71 3 63 98 83 34 1 38 5 35 9 89 3 62] arr[10]: 35
-
-
全切片:获取所有元素
-
[:]:省略起始索引和结束索引,代表选取数组中所有元素,等价于直接打印arr。
-
代码
print(f"arr[:]: {arr[:]}")-
结果
arr[:]: [40 71 3 63 98 83 34 1 38 5 35 9 89 3 62]
-
-
范围切片:左闭右开 [起始索引, 结束索引)
-
语法:
arr[start:end]; -
规则:包含 start,不包含 end → 左闭右开
[start, end); -
arr[2:5]:选取索引 2、3、4 共 3 个元素。
-
代码
print(f"arr[2:5]: {arr[2:5]}")-
结果
arr[2:5]: [ 3 63 98]
-
-
slice对象切片:指定 (起始,结束,步长)
-
slice(start, stop, step):Python 内置切片对象,等价于简写[start:stop:step]; -
参数含义:
-
2:起始索引; -
15:结束索引(不包含); -
3:步长(每隔 3 个元素取 1 个);
-
等价简写:
arr[2:15:3]。
-
代码
print(f"arr[slice(2,15,3)]: {arr[slice(2,15,3)]}")-
结果
arr[slice(2,15,3)]: [ 3 83 38 9 62]
-
-
布尔索引:根据条件筛选元素
-
arr>50会生成一个布尔数组(元素为True/False); -
用布尔数组作为索引,只保留值为 True 的元素;
-
代码
print(f"arr[arr>50]: {arr[arr>50]}")-
结果
arr[arr>50]: [71 63 98 83 89 62]
-
-
多条件布尔索引:& 表示且,| 表示或
-
逻辑且:用
&,不能用and; -
逻辑或:用
|,不能用or; -
每个条件必须加括号
(); -
作用:筛选出 大于 50 且 小于 80 的元素。
-
代码
print(f"arr[(arr>50) & (arr<80)]: {arr[(arr>50) & (arr<80)]}")-
结果
arr[(arr>50) & (arr<80)]: [71 63 62]
-
-
布尔索引修改元素:满足条件的元素直接赋值为0
-
布尔索引不仅能筛选,还能直接赋值修改;
-
作用:将数组中所有满足 50 < 元素 < 80的元素,批量修改为
0。
-
代码
arr[(arr>50) & (arr<80)] = 0 print(f"arr: {arr}")-
结果
arr: [40 0 3 0 98 83 34 1 38 5 35 9 89 3 0]
-
5.2 二维数组的索引与切片
-
取单个元素:行索引,列索引
-
二维索引语法:
arr[行索引, 列索引] -
规则:行、列索引都从 0 开始
-
arr[1,3]= 第 2 行、第 4 列 的元素
-
代码
import numpy as np arr = np.random.randint(1,100,(4,8)) print(arr) print(f"arr[1,3]: {arr[1,3]}")-
结果
[[73 92 98 7 91 82 39 76] [10 31 52 38 19 25 55 98] [25 32 75 2 84 52 16 65] [13 69 47 48 15 45 52 17]] arr[1,3]: 38
-
-
取全部元素
-
[:]= 所有行 + 所有列 -
等价于直接打印
arr,输出完整二维数组。
-
代码
print(f"arr[:]:\n {arr[:]}")-
结果
arr[:]: [[73 92 98 7 91 82 39 76] [10 31 52 38 19 25 55 98] [25 32 75 2 84 52 16 65] [13 69 47 48 15 45 52 17]]
-
-
取整行:第2行所有列
-
语法:
arr[行号, :] -
:代表所有列 -
arr[1,:]= 第 2 行全部元素(结果是一维数组)
-
代码
print(f"arr[1,:]: {arr[1,:]}")-
结果
arr[1,:]: [10 31 52 38 19 25 55 98]
-
-
取整列:所有行第3列
-
语法:
arr[:, 列号] -
:代表所有行 -
arr[:,2]= 第 3 列全部元素(结果是一维数组)
-
代码
print(f"arr[:,2]: {arr[:,2]}")-
结果
arr[:,2]: [98 52 75 47]
-
-
区域切片:第2行,第3列~第5列
-
语法:
arr[行, 列起始:列结束] -
规则:左闭右开
-
arr[1,2:5]= 第 2 行,第 3 列、第 4 列、第 5 列 元素
-
代码
print(f"arr[1,2:5]: {arr[1,2:5]}")-
结果
arr[1,2:5]: [52 38 19]
-
-
全局布尔索引:所有>50的元素(结果自动展平为一维)
-
对整个二维数组做条件筛选;
-
自动把满足条件的元素全部抽出来,展平成一维数组;
-
用途:快速查找整个矩阵中符合条件的所有值。
-
代码
print(f"arr[arr>50]:{arr[arr>50]}")-
结果
arr[arr>50]:[73 92 98 91 82 76 52 55 98 75 84 52 65 69 52]
-
-
行内布尔索引:(先取行,再筛选) ,第2行中>50的元素
-
arr[1,:]→ 先拿到第 2 行(一维) -
arr[1,:]>50→ 生成布尔条件 -
再用布尔索引筛选 → 得到第 2 行中大于 50 的元素
-
代码
print(f"arr[1,:][arr[1,:]>50]:{arr[1,:][arr[1,:]>50]}")-
结果
arr[1,:][arr[1,:]>50]:[52 55 98]
-
6. ndarray的运算
6.1 数组与数组间的运算
6.1.1 一维数组的数组间运算
-
NumPy数组直接进行 加、减、乘、除 运算
-
规则:对应位置元素直接运算,无需写循环!
-
运算逻辑:
-
a[0]+b[0],a[1]+b[1],a[2]+b[2]
-
减、乘、除同理
-
-
代码
import numpy as np a = np.array([1, 2, 3]) b = np.array([4, 5, 6]) print(f"a+b: {a+b}") # 对应位置元素相加 print(f"a-b: {a-b}") # 对应位置元素相减 print(f"a*b: {a*b}") # 对应位置元素相乘 print(f"a/b: {a/b}") # 对应位置元素相除-
结果
a+b: [5 7 9] a-b: [-3 -3 -3] a*b: [ 4 10 18] a/b: [0.25 0.4 0.5 ]
-
-
Python原生列表的运算
-
列表
+不是数学加法,是拼接:把两个列表首尾连在一起。 -
Python 列表直接不支持
-、*、/运算,运行会直接报错!
-
代码
c = [1, 2, 3] d = [4, 5, 6] # Python列表的 + 是拼接,不是数学加法 print(f"c+d: {c+d}") # Python列表**不能直接**做减、乘、除,必须用循环遍历元素 for i in range(len(c)): c[i] += d[i] print(f"c: {c}")-
结果
c+d: [1, 2, 3, 4, 5, 6] c: [5, 7, 9]
-
6.1.2 多维数组的数组间运算
所有运算都是:相同行、相同列的元素,一一对应计算
两个多维数组的 shape(形状)必须完全一致
-
对应元素相加
第 1 行:
1+7=8、2+8=10、3+9=12第 2 行:
4+4=8、5+5=10、6+6=12第 3 行:
7+1=8、8+2=10、9+3=12-
代码
import numpy as np a = np.array([[1, 2, 3], [4, 5, 6], [7, 8, 9]]) b = np.array([[7, 8, 9], [4, 5, 6], [1, 2, 3]]) print(f"a+b: \n{a+b}")-
结果
a+b: [[ 8 10 12] [ 8 10 12] [ 8 10 12]]
-
-
对应元素相减
-
代码
print(f"a-b: \n{a-b}")-
结果
a-b: [[-6 -6 -6] [ 0 0 0] [ 6 6 6]]
-
-
对应元素相乘(点乘,不是矩阵乘法!)
-
重点:这是元素级乘法(点乘),不是线性代数里的矩阵乘法!
-
规则:
a[0,0]*b[0,0]、a[0,1]*b[0,1]... 逐个相乘。
-
代码
print(f"a*b: \n{a*b}")-
结果
a*b: [[ 7 16 27] [16 25 36] [ 7 16 27]]
-
-
对应元素相除,np.round保留2位小数
-
a/b:对应元素相除,结果是浮点数; -
np.round(数值, 2):NumPy 自带函数,保留 2 位小数。
-
代码
print(f"a/b: \n{np.round(a/b, 2)}")-
结果
a/b: [[0.14 0.25 0.33] [1. 1. 1. ] [7. 4. 3. ]]
-
6.2 数组与标量之间的运算
6.2.1 一维数组的运算
标量运算:数组里的每个元素都和这个数字单独计算
-
每个元素 +1
a + 1
-
等价于:[[1+1, 2+1, 3+1]]
-
结果:[[2 3 4]]
-
代码
import numpy as np a = np.array([[1, 2, 3]]) print(f"a+1: {a+1}")-
结果
a+1: [[2 3 4]]
-
-
每个元素 ×2
a * 2
-
等价于:[[1×2, 2×2, 3×2]]
-
结果:[[2 4 6]]
-
代码
print(f"a*2: {a*2}")-
结果
a*2: [[2 4 6]]
-
-
每个元素 平方
a ** 2
-
等价于:[[1², 2², 3²]]
-
结果:[[1 4 9]]
-
代码
print(f"a**2: {a**2}")-
结果
a**2: [[1 4 9]]
-
-
每个元素 ÷2,保留1位小数
a / 2
-
等价于:[[1/2, 2/2, 3/2]]
-
np.round 保留1位小数 → [[0.5 1. 1.5]]
-
代码
print(f"a/2: {np.round(a/2, 1)}")-
结果
a/2: [[0.5 1. 1.5]]
-
6.2.2 多维数组的运算
标量会自动广播到数组的每一个元素,逐个计算
-
代码
import numpy as np
b = np.array([[1, 2, 3], [4, 5, 6], [7, 8, 9]])
# 1. 每个元素 +1
print(f"b+1: \n{b+1}")
# 2. 每个元素 ×2
print(f"b*2: \n{b*2}")
# 3. 每个元素 平方(2次方)
print(f"b**2: \n{b**2}")
# 4. 每个元素 ÷2,np.round保留1位小数
print(f"b/2: \n{np.round(b/2, 1)}")
-
结果
b+1: [[ 2 3 4] [ 5 6 7] [ 8 9 10]] b*2: [[ 2 4 6] [ 8 10 12] [14 16 18]] b**2: [[ 1 4 9] [16 25 36] [49 64 81]] b/2: [[0.5 1. 1.5] [2. 2.5 3. ] [3.5 4. 4.5]]
6.3 广播机制
广播机制允许 NumPy 在算术运算期间处理不同形状的数组。它会自动"扩展"较小的数组以匹配较大数组的形状,从而进行元素级运算。
两个数组要能广播,必须满足以下条件之一:
维度数相同,且每个维度的大小相同或其中一个为 1;
维度数不同,从最后一个维度向前比较,每个维度大小相同或其中一个为 1
-
代码
# 广播机制:不同形状的数组,自动扩展成相同形状,再做元素级运算 import numpy as np # 形状 (1,3) → 1行3列 a = np.array([1, 2, 3]) # 形状 (3,1) → 3行1列 b = np.array([[4], [5], [6]]) # 两个数组形状不同 → 触发广播机制,自动扩展后运算 print(f"a+b: \n{a+b}") print(f"b-a: \n{b-a}") print(f"a*b: \n{a*b}") print(f"a/b: \n{np.round(a/b, 1)}") print(f"a**b: \n{a**b}") -
结果
a+b: [[5 6 7] [6 7 8] [7 8 9]] b-a: [[3 2 1] [4 3 2] [5 4 3]] a*b: [[ 4 8 12] [ 5 10 15] [ 6 12 18]] a/b: [[0.2 0.5 0.8] [0.2 0.4 0.6] [0.2 0.3 0.5]] a**b: [[ 1 16 81] [ 1 32 243] [ 1 64 729]]
-
数组的形状
a = [1, 2, 3] → shape (1, 3) 1行3列 b = [[4], [5], [6]] → shape (3, 1) 3行1列 -
广播会把两个数组自动扩展成相同形状(3×3),再逐元素计算:
-
a 扩展成 3 行 3 列
1 2 3 1 2 3 1 2 3
-
b 扩展成 3 行 3 列
4 4 4 5 5 5 6 6 6
-
然后对应位置运算:比如
a + b结果1+4 2+4 3+4 1+5 2+5 3+5 1+6 2+6 3+6
-
6.4 矩阵运算
推荐写法(简洁): a @ b
函数写法: np.matmul(a, b)
点积函数(二维等价): np.dot(a, b)
二维时:
np.dot=@=np.matmul
@不支持一维运算,np.dot支持
-
代码
import numpy as np a = np.array([[1, 2, 3], [4, 5, 6], [7, 8, 9]]) b = np.array([[4, 5, 6], [7, 8, 9], [1, 2, 3]]) # 矩阵乘法 符号:@ print(f"a @ b: \n{a @ b}") print(f"np.dot(a, b): \n{np.dot(a, b)}") -
结果
a @ b: [[ 21 27 33] [ 57 72 87] [ 93 117 141]] np.dot(a, b): [[ 21 27 33] [ 57 72 87] [ 93 117 141]]
7. numpy中的常用函数
| 基本数学函数 | 统计函数 | 比较函数 | 其他函数 | 排序函数 |
|---|---|---|---|---|
| np.sqrt(x)#开根 | np.sum(x)#求和 | np.greater(a, b)#是否大于 | np.concatenate((a, b))#数组拼接 | np.sort(x)#升序 |
| np.exp(x)#e的x次幂 | np.mean(x)#平均值 | np.less(a, b)#是否小于 | np.split(x, indices)#数组切割 | x.sort()#原地排序 |
| np.log(x)#ln x | np.median(x)#中位数 | np.equal(a, b)#是否等于 | np.reshape(x, shape)#重新定义形状 | np.argsort(x)#索引(单键) |
| np.sin(x)#三角函数 | np.var(x)#方差 | np.logical_and(a, b)#与 | np.copy(x) | np.lexsort(keys)#索引(多键) |
| np.abs(x)#绝对值 | np.std(x)#标准差 | np.logical_or(a, b)#或 | np.isnan(x)#检测缺失值 | |
| np.power(a, b)#a的b次幂 | np.min(x) / np.max(x) | np.logical_not(a, b)#非 | np.unique(x)#去重 | |
| np.round(x, n)#四舍五入 | np.argmin(x)/np.argmax(x)#索引 | np.where(condition, x, y)#自定义条件 | ||
| np.ceil(x)#向上取整 | np.percentile(x, q)#分位数 | np.any(condition)#是否满足条件 | ||
| np.floor(x)#向下取整 | np.cumsum(x)#累积和 | np.all(condition)#是否满足所有条件 | ||
| np.cumprod(x)#累积积 | np.select(condition, x, y)#选择条件满足的元素 |
7.1 基本数学函数
1. np.sqrt (数组)
np.sqrt (数组) → 开平方
-
代码
import numpy as np a = np.array([1, 4, 9]) b = np.array([2.2, 3.6, 5.9]) print(f"np.sqrt(a): {np.sqrt(a)}") # 开平方(根号) -
结果
np.sqrt(a): [1. 2. 3.]
2. np.exp(x)
np.exp(x) → e^x 自然常数 e 的 x 次方:e ≈ 2.718
-
代码
print(f"np.exp(1): {np.exp(1)}") # 自然指数 e^x -
结果
np.exp(1): 2.718281828459045
3. np.log (x)
np.log (x) → 自然对数 ln (x)
-
代码
print(f"np.log(1): {np.log(1)}") # 自然对数 ln(x) -
结果
np.log(1): 0.0
4. np.sin (x)
np.sin (x) → 正弦函数:np.pi = π = 3.14159
-
代码
print(f"np.sin(np.pi/2): {np.sin(np.pi/2)}") # 正弦函数(π=3.14159) -
结果
np.sin(np.pi/2): 1.0
5. np.abs (x)
np.abs (x) → 绝对值
-
代码
print(f"np.abs(-2): {np.abs(-2)}") -
结果
np.abs(-2): 2
6. np.power (数组,n)
np.power (数组,n) → 元素的 n 次方
-
代码
print(f"np.power(a, 2): {np.power(a, 2)}") # 幂运算(a 的 2 次方) -
结果
np.power(a, 2): [ 1 16 81]
7. np.round (x)
np.round (x) → 四舍五入
-
代码
print(f"np.round(b): {np.round(b)}") -
结果
np.round(b): [2. 4. 6.]
8. np.ceil (x)
np.ceil (x) → 向上取整(往大取)
-
代码
print(f"np.ceil(b): {np.ceil(b)}") # 向上取整(天花板) -
结果
np.ceil(b): [3. 4. 6.]
9. np.floor (x)
np.floor (x) → 向下取整(往小取)
-
代码
print(f"np.floor(b): {np.floor(b)}") # 向下取整(地板) -
结果
np.floor(b): [2. 3. 5.]
10. np.isnan (x)
np.isnan (x) → 判断是否为缺失值:返回 True / False
-
代码
print(f"np.isnan(1,2,np.nan,3): {np.isnan([1,2,np.nan,3])}") # 判断是否为缺失值 NaN -
结果
np.isnan(1,2,np.nan,3): [False False True False]
7.2 统计函数
1. np.sum(arr)
np.sum(arr) → 总和: 把数组里所有元素加起来
-
代码
import numpy as np np.random.seed(0) arr = np.random.randint(1,20,8) print(f"arr: {arr}") print(f"np.sum(arr): {np.sum(arr)}") # 求和 -
结果
arr: [13 16 1 4 4 8 10 19] np.sum(arr): 75
2. np.mean(arr)
np.mean(arr) → 平均值:总和 / 元素个数
-
代码
print(f"np.mean(arr): {np.mean(arr)}") # 平均值 -
结果
# arr: [13 16 1 4 4 8 10 19] np.mean(arr): 9.375
3. np.median(arr)
np.median(arr) → 中位数:把数组从小到大排序,取中间位置的数 偶数个元素 → 中间两个数的平均值
-
代码
print(f"np.median(arr): {np.median(arr)}") # 中位数 -
结果
# arr: [13 16 1 4 4 8 10 19] np.median(arr): 9.0
4. np.var(arr)
np.var(arr) → 方差:衡量数据波动大小、离散程度 数值越大,数据越不稳定、越分散 公式:每个数据与平均值的差的平方,再求平均
-
代码
print(f"np.var(arr): {np.var(arr)}") # 方差 -
结果
np.var(arr): 34.984375
5. np.std(arr)
np.std(arr) → 标准差:方差开平方,同样表示数据波动程度 单位和原数据一致,更直观。波动越大,标准差越大
-
代码
print(f"np.std(arr): {np.std(arr)}") # 标准差 -
结果
np.std(arr): 5.91475908216049
6. np.min(arr) / np.max(arr)
-
代码
print(f"np.min(arr): {np.min(arr)}") # 最小值 print(f"np.max(arr): {np.max(arr)}") # 最大值 -
结果
# arr: [13 16 1 4 4 8 10 19] np.min(arr): 1 np.max(arr): 19
7. np.percentile(arr, 25)
np.percentile(arr, 25) → 25% 分位数!!!先排序后找分位
25% 分位数 = 下四分位数
50% 分位数 = 中位数
75% 分位数 = 上四分位数
-
代码
print(f"np.percentile(arr, 25): {np.percentile(arr, 25)}") # 分位数 -
结果
# arr: [13 16 1 4 4 8 10 19] np.percentile(arr, 25): 4.0
8. np.cumsum(arr)
np.cumsum(arr) → 累积和:从第一个数开始,一步步累加
-
代码
# 累积和:每个位置的值 = 从开始到当前位置所有元素的总和 print(f"np.cumsum(arr): {np.cumsum(arr)}") -
结果
# arr: [13 16 1 4 4 8 10 19] np.cumsum(arr): [13 29 30 34 38 46 56 75] # 第1位:13 # 第2位:13+16=29 # 第3位:29+1=30 # 第4位:30+4=34 # ...
9. np.cumprod(arr)
np.cumprod(arr) → 累积积:从第一个数开始,一步步累乘
-
代码
# 累积积:每个位置的值 = 从开始到当前位置所有元素乘积 print(f"np.cumprod(arr): {np.cumprod(arr)}") -
结果
# arr: [13 16 1 4 4 8 10 19] np.cumprod(arr): [ 13 208 208 832 3328 26624 266240 5058560] # 第1位:13 # 第2位:13×16=208 # 第3位:208×1=208 # 第4位:208×4=832 # ...
7.3 比较函数
1. 比较函数(返回布尔数组)
作用:两个数组对应位置比较,输出
True/False
np.greater(a, b) -> a > b (是否大于)
np.less(a, b) -> a < b (是否小于)
np.equal(a, b) -> a == b (是否等于)
-
代码
import numpy as np a = np.array([1, 5, 10, 15, 20]) b = np.array([2, 5, 8, 12, 20]) # 1. np.greater(a, b) -> a > b (是否大于) print(f"np.greater(a, b): {np.greater(a, b)}") # [False, False, True, True, False] # 2. np.less(a, b) -> a < b (是否小于) print(f"np.less(a, b): {np.less(a, b)}") # [True, False, False, False, False] # 3. np.equal(a, b) -> a == b (是否等于) print(f"np.equal(a, b): {np.equal(a, b)}") # [False, True, False, False, True] -
结果
np.greater(a, b): [False False True True False] np.less(a, b): [ True False False False False] np.equal(a, b): [False True False False True]
2. 逻辑运算(与 / 或 / 非)
专门用于布尔数组运算:
np.logical_and→ 且(两个都 True 才 True)
np.logical_or→ 或(一个 True 就 True)
np.logical_not→ 非(取反)
-
代码
# 布尔数组 c = np.array([True, False, True, False, True]) d = np.array([True, True, False, False, True]) # 4. np.logical_and - 与运算 -> 且 & (两个都True才True) print(f"np.logical_and(c, d): {np.logical_and(c, d)}") # [True, False, False, False, True] # 5. np.logical_or - 或运算 -> 或 | (一个True就True) print(f"np.logical_or(c, d): {np.logical_or(c, d)}") # [True, True, True, False, True] # 6. np.logical_not - 非运算 -> 非 ~ (True变False) print(f"np.logical_not(c): {np.logical_not(c)}") # [False, True, False, True, False] -
结果
np.logical_and(c, d): [ True False False False True] np.logical_or(c, d): [ True True True False True] np.logical_not(c): [False True False True False]
3. np.where(条件, 真时取值, 假时取值)
根据条件批量替换 / 赋值 - 自定义条件(类似三元运算符)
打标签
数据清洗(小于 10 替换为 0)
-
代码
print(f"np.where(a > 10, '大', '小'): {np.where(a > 10, '大', '小')}") # ['小' '小' '小' '大' '大'] # 实际应用:将小于10的数替换为0 print(f"np.where(a < 10, 0, a): {np.where(a < 10, 0, a)}") # [ 0 0 10 15 20] -
结果
np.where(a > 10, '大', '小'): ['小' '小' '小' '大' '大'] np.where(a < 10, 0, a): [ 0 0 10 15 20]
4. np.any / np.all(返回单个 True/False)
np.any(条件):任意一个满足 → Truenp.all(条件):全部满足 → True
-
代码
# 8. np.any - 是否满足条件(任意一个为True就返回True) # a = np.array([1, 5, 10, 15, 20]) print(f"np.any(a > 15): {np.any(a > 15)}") # True (20>15) print(f"np.any(a > 100): {np.any(a > 100)}") # False (所有数都小于100) # 9. np.all - 是否满足所有条件(全部为True才返回True) print(f"np.all(a > 0): {np.all(a > 0)}") # True (所有数都大于0) print(f"np.all(a > 5): {np.all(a > 5)}") # False (1和5不大于5) -
结果
np.any(a > 15): True np.any(a > 100): False np.all(a > 0): True np.all(a > 5): False
#####
5. np.select(多条件判断)
超过 2 个条件时用它! 语法:p.select([条件1, 条件2, 条件3], [结果1, 结果2, 结果3])
-
代码
# 10. np.select - 多条件选择 # 语法: np.select(条件列表, 结果列表, default=默认值) conditions = [a < 5, a < 15, a >= 15] choices = ['小', '中', '大'] print(f"np.select(conditions, choices, default='未知'): {np.select(conditions, choices, default='未知')}") # ['小' '小' '中' '中' '大'] -
结果
np.select(conditions, choices, default='未知'): ['小' '中' '中' '大' '大']
7.4 排序函数
1. np.sort (数组)
np.sort (数组) → 升序排序(返回新数组) 特点:原数组不变,返回排好序的新数组
二维数组排序(axis 控制方向):
axis=1→ 按行排序(每行内部从小到大)
axis=0→ 按列排序(每列内部从小到大)
-
代码
import numpy as np # 1. np.sort - 升序排序(返回新数组) # 一维数组排序 arr1d = np.array([5, 2, 8, 1, 9, 3]) sorted_arr = np.sort(arr1d) print(f"原数组: {arr1d}") # [5 2 8 1 9 3] (不变) print(f"排序后: {sorted_arr}") # [1 2 3 5 8 9] # 二维数组排序 arr2d = np.array([[3, 1, 2], [9, 7, 8]]) print(f"按行排序(axis=1):\n{np.sort(arr2d, axis=1)}") print(f"按列排序(axis=0):\n{np.sort(arr2d, axis=0)}") -
结果
原数组: [5 2 8 1 9 3] 排序后: [1 2 3 5 8 9] 按行排序(axis=1): [[1 2 3] [7 8 9]] 按列排序(axis=0): [[3 1 2] [9 7 8]]
2. 数组.sort ()
数组.sort () → 原地排序 特点:直接修改原数组,不返回新数组
-
代码
# 2. x.sort - 原地排序(修改原数组) arr = np.array([5, 2, 8, 1, 9, 3]) arr.sort() print(f"原地排序后: {arr}") # [1 2 3 5 8 9] (原数组已改变) -
结果
原地排序后: [1 2 3 5 8 9]
3. np.argsort (数组)
np.argsort (数组) → 返回排序索引(超级重要)
不是返回排序后的值,而是返回值对应的索引!
-
代码
# 3. np.argsort - 获取排序索引(单键) arr = np.array([5, 2, 8, 1, 9, 3]) indices = np.argsort(arr) print(f"排序索引: {indices}") # [3 1 5 0 2 4] print(f"使用索引排序: {arr[indices]}") # [1 2 3 5 8 9] # 实际应用: 找出成绩最高的3个学生索引 scores = np.array([85, 92, 78, 95, 88, 91]) top3_indices = np.argsort(scores)[-3:][::-1] # 降序取前3 print(f"成绩最高的3个索引: {top3_indices}") # [3 1 5] print(f"对应的成绩: {scores[top3_indices]}") # [95 92 91] -
结果
排序索引: [3 1 5 0 2 4] 使用索引排序: [1 2 3 5 8 9] 成绩最高的3个索引: [3 1 5] 对应的成绩: [95 92 91]
4. np.lexsort()
np.lexsort → 多键排序(先按 次键,再按 主键)
语法:np.lexsort((次键, 主键))
多条件排序:先排班级,同班再排成绩
np.lexsort 里,越靠后的键,优先级越高!
-
代码
# 4. np.lexsort - 获取排序索引(多键) # 学生数据: 班级、成绩 classes = np.array([2, 1, 2, 1, 2]) scores = np.array([85, 92, 78, 95, 88]) # 先按班级排序,班级相同再按成绩排序(最后一个键是主键) indices = np.lexsort((scores, classes)) print(f"多键排序索引: {indices}") print(f"排序后班级: {classes[indices]}") # [1 1 2 2 2] print(f"排序后成绩: {scores[indices]}") # [92 95 78 88 85] # 降序排序技巧(加负号) indices_desc = np.lexsort((-scores, classes)) print(f"成绩降序索引: {indices_desc}") print(f"降序成绩: {scores[indices_desc]}") # [95 92 88 85 78] -
结果
多键排序索引: [1 3 2 0 4] 排序后班级: [1 1 2 2 2] 排序后成绩: [92 95 78 85 88] 成绩降序索引: [3 1 4 0 2] 降序成绩: [95 92 88 85 78]
7.5 其他函数
1. np.concatenate()
np.concatenate → 数组拼接:把多个数组按行或按列拼在一起。
二维数组拼接:
axis=0:按行拼接(往下加行)
axis=1:按列拼接(往右加列)
-
代码
import numpy as np # 1. np.concatenate - 数组拼接 a = np.array([1, 2, 3]) b = np.array([4, 5, 6]) print(f"np.concatenate((a, b)): {np.concatenate((a, b))}") # [1 2 3 4 5 6] # 二维数组拼接 a2d = np.array([[1, 2], [3, 4]]) b2d = np.array([[5, 6]]) print(f"按行拼接(axis=0):\n{np.concatenate((a2d, b2d), axis=0)}") print(f"按列拼接(axis=1):\n{np.concatenate((a2d, a2d), axis=1)}") -
结果
np.concatenate((a, b)): [1 2 3 4 5 6] 按行拼接(axis=0): [[1 2] [3 4] [5 6]] 按列拼接(axis=1): [[1 2 1 2] [3 4 3 4]]
2. np.split()
np.split → 数组切割:把一个数组切成几段。
① 平均切 3 份 ② 在指定位置切
-
代码
# 2. np.split - 数组切割 arr = np.array([1, 2, 3, 4, 5, 6]) # 平均分成3等份 print(f"np.split(arr, 3): {np.split(arr, 3)}") # 输出: [array([1, 2]), array([3, 4]), array([5, 6])] # 在指定位置切割 print(f"np.split(arr, [1, 3]): {np.split(arr, [1, 3])}") # 输出: [array([1]), array([2, 3]), array([4, 5, 6])] -
结果
np.split(arr, 3): [array([1, 2]), array([3, 4]), array([5, 6])] np.split(arr, [1, 3]): [array([1]), array([2, 3]), array([4, 5, 6])]
3. np.reshape()
np.reshape → 改变数组形状:把数组变成你想要的 行 × 列 形状。
最实用技巧:
-1自动计算 --> arr.reshape(x, -1) 我只要 x 行,列数你自动帮我算!
-
代码
# 3. np.reshape - 重新定义形状 arr = np.array([1, 2, 3, 4, 5, 6]) print(f"reshape为2x3:\n{arr.reshape(2, 3)}") print(f"reshape为3x2:\n{arr.reshape(3, 2)}") # 使用-1自动计算维度 print(f"reshape为2x(-1):\n{arr.reshape(2, -1)}") # 自动计算列数为3 -
结果
reshape为2x3: [[1 2 3] [4 5 6]] reshape为3x2: [[1 2] [3 4] [5 6]] reshape为2x(-1): [[1 2 3] [4 5 6]]
4. np.copy()
np.copy → 数组复制(深拷贝)
如果你直接
b = a,修改 b 会把 a 也改了。 用np.copy(a):复制一个完全独立的新数组,修改新数组不影响原数组!
-
代码
# 4. np.copy - 数组复制 a = np.array([1, 2, 3]) b = np.copy(a) # 深拷贝 b[0] = 100 print(f"原数组a: {a}") # [1 2 3] (不受影响) print(f"复制数组b: {b}") # [100 2 3] -
结果
原数组a: [1 2 3] 复制数组b: [100 2 3]
5. np.isnan()
np.isnan → 检测缺失值(数据清洗必备)
np.nan= 缺失值配合 np.where 替换缺失值
-
代码
# 5. np.isnan - 检测缺失值 arr = np.array([1, 2, np.nan, 4, np.nan]) print(f"np.isnan(arr): {np.isnan(arr)}") # [False False True False True] # 配合where使用,替换NaN print(f"替换NaN为0: {np.where(np.isnan(arr), 0, arr)}") -
结果
np.isnan(arr): [False False True False True] 替换NaN为0: [1. 2. 0. 4. 0.]
6. np.unique()
np.unique → 数组去重
自动:去重、排序、返回唯一值
进阶:统计每个数字出现几次
unique_vals:不重复的值
counts:每个值出现的次数
-
代码
# 6. np.unique - 去重 arr = np.array([3, 1, 2, 3, 2, 1, 4]) print(f"np.unique(arr): {np.unique(arr)}") # [1 2 3 4] # 返回索引和计数 unique_vals, counts = np.unique(arr, return_counts=True) print(f"唯一值: {unique_vals}") # [1 2 3 4] print(f"出现次数: {counts}") # [2 2 2 1] -
结果
np.unique(arr): [1 2 3 4] 唯一值: [1 2 3 4] 出现次数: [2 2 2 1]
二、Pandas
| 特性 | Series | DataFrame |
|---|---|---|
| 维度 | 一维 | 二维 |
| 索引 | 单索引 | 行索引+列名 |
| 数据存储 | 同质化数据类型 | 各列可不同数据类型 |
| 类比 | Excel单列 | 整张Excel工作表 |
| 创建方式 | pd.Series([1,2,3]) | pd.DataFrame({'col':[1,2,3]}) |
(一) Series
1. series的创建
1.1 索引
-
代码
import pandas as pd # 默认索引 s = pd.Series([10,32,11,21,54]) print(f"默认索引:\n{s}") # 自定义索引 s = pd.Series([10,32,11,21,54],index=['a','b','c','d','e']) print(f"自定义索引:\n{s}") # 定义name s = pd.Series([10,32,11,21,54],index=['a','b','c','d','e'],name='score') print(f"定义name:\n{s}") -
结果
默认索引: 0 10 1 32 2 11 3 21 4 54 dtype: int64 自定义索引: a 10 b 32 c 11 d 21 e 54 dtype: int64 定义name: a 10 b 32 c 11 d 21 e 54 Name: score, dtype: int64
1.2 字典类
格式:{ 索引: 数据, 索引: 数据... }
-
代码
# 通过字典创建 s = pd.Series({'a':10,'b':32,'c':11,'d':21,'e':54}) print(f"通过字典创建:\n{s}") # 获取指定索引的数据 s1 = pd.Series(s,index=['a','c','d']) print(f"获取指定索引的数据:\n{s1}") -
结果
通过字典创建: a 10 b 32 c 11 d 21 e 54 dtype: int64 获取指定索引的数据: a 10 c 11 d 21 dtype: int64
2. series的属性
| 属性 | 说明 | 属性 | 说明 |
|---|---|---|---|
| index | Series的索引对象 | loc [ ] | 显式索引,按标签索引或切片 |
| values | Series的值 | iloc [ ] | 隐式索引,按位置索引或切片 |
| dtype或dtypes | Series的元素类型 | at [ ] | 使用标签访问单个元素 |
| shape | Series的形状 | iat [ ] | 使用位置访问单个元素 |
| ndim | Series的维度 | ||
| size | Series的元素个数 | ||
| name | Series的名称 |
2.1 Series 常用属性
这些属性不用加括号,直接获取信息
-
代码
import pandas as pd # 创建Series s = pd.Series([10,32,11,21,54], index=['a','b','c','d','e'], name='score') # ============ 1. 常用属性 ============ print(f"获取index:\n{s.index}") # 索引 print(f"获取values:{s.values}") # 值 print(f"获取dtype:{s.dtype}") # 数据类型 print(f"获取shape:{s.shape}") # 形状 print(f"获取ndim:{s.ndim}") # 维度 print(f"获取size:{s.size}") # 元素个数 print(f"获取name:{s.name}") # 名字 -
结果
获取index: Index(['a', 'b', 'c', 'd', 'e'], dtype='str') 获取values:[10 32 11 21 54] 获取dtype:int64 获取shape:(5,) 获取ndim:1 获取size:5 获取name:score
2.2 显式索引 vs 隐式索引
1. 显式索引:loc 和 at
① s.loc['a':'c']:
用自定义索引名
包含结束位置(a 到 c,包含 c)
结果:a、b、c 三个数据
② s.at['a']:
获取单个值
速度更快,专门取单个值
结果:
10
-
代码
# 显式索引(用自定义的标签) print(f"获取指定索引的数据(显式索引loc):\n{s.loc['a':'c']}") # 获取单个值 print(f"获取单个数据(显式at):\n{s.at['a']}") -
结果
获取指定索引的数据(显式索引): a 10 b 32 c 11 Name: score, dtype: int64 获取指定索引的数据(显式索引): 10
2. 隐式索引:iloc 和 iat
① s.iloc[1:4]:
用0 开始的位置
左闭右开,不包含结束位置
取:1、2、3 位置 → b、c、d
② s.iat[1]:
获取第 1 个位置的值
结果:
32
-
代码
# 隐式索引(用0,1,2...位置) print(f"获取指定索引的数据(隐式索引iloc):\n{s.iloc[1:4]}") # 获取单个值 print(f"获取单个数据(隐式iat):\n{s.iat[1]}") -
结果
获取指定索引的数据(隐式索引): b 32 c 11 d 21 Name: score, dtype: int64 获取指定索引的数据(隐式索引): 32
2.3 访问series数据
1. 三种获取单个值的方法
-
代码
import pandas as pd # 创建Series s = pd.Series([10,32,11,21,54], index=['a','b','c','d','e'], name='score') # 三种获取单个值的方式 print(f"获取指定索引的数据(s['a']):{s['a']}") print(f"获取指定索引的数据(s.a):{s.a}") print(f"获取指定索引的数据(s.get('a')):{s.get('a')}") -
结果
获取指定索引的数据(s['a']):10 获取指定索引的数据(s.a):10 获取指定索引的数据(s.get('a')):10
2. 布尔索引(条件筛选数据)
-
代码
# 布尔索引(条件筛选) print(s) print(f"s>20:\n{s[s>20]}") print(f"s[(s>20) & (s<50)]:\n{s[(s>20) & (s<50)]}") -
结果
a 10 b 32 c 11 d 21 e 54 Name: score, dtype: int64 s>20: b 32 d 21 e 54 Name: score, dtype: int64 s[(s>20) & (s<50)]: b 32 d 21 Name: score, dtype: int64
3. series的常用方法
| 方法 | 说明 | 方法 | 说明 |
|---|---|---|---|
| head() | 查看前 n 行数据,默认 5 行 | value_counts() | 每个唯一值的出现次数 |
| tail() | 查看后 n 行数据,默认 5 行 | count() | 非缺失值数量 |
| isin() | 判断元素是否包含在参数集合中 | nunique() | 唯一值个数(去重) |
| isna() | 判断是否为缺失值(如 NaN 或 None) | unique() | 获取去重后的值数组 |
| sum() | 求和,自动忽略缺失值 | drop_duplicates() | 去除重复项 |
| mean() | 平均值 | sample() | 随机抽样 |
| min() | 最小值 | resample() | 按时间进行重采样 |
| max() | 最大值 | sort_index() | 按索引排序 |
| var() | 方差 | sort_values() | 按值排序 |
| std() | 标准差(波动率) | replace() | 替换值 |
| median() | 中位数 | keys() | 返回 Series 的索引对象 |
| mode() | 众数(可返回多个) | diff() | 计算相邻元素之间的差值(一阶差分) |
| quantile(q) | 分位数,q 取 0~1 之间(如 0.25 表示 25% 分位数) | pd.date_range() | 生成日期范围 |
| describe() | 常见统计信息(count、mean、std、min、25%、50%、75%、max) | rolling() | 滚动窗口计算 |
1. 查看数据:head() / tail()
-
代码
import pandas as pd import numpy as np s = pd.Series([77,32,np.nan,None,54,12,77],index=['a','b','c','d','e','f','g'],name='score') print(f"s:\n{s}") print(f"s.head(3):\n{s.head(3)}") s.head(3) print(f"s.tail(3):\n{s.tail(3)}") s.tail(3) -
结果
s: a 77.0 b 32.0 c NaN d NaN e 54.0 f 12.0 g 77.0 Name: score, dtype: float64 s.head(3): a 77.0 b 32.0 c NaN Name: score, dtype: float64

s.tail(3): e 54.0 f 12.0 g 77.0 Name: score, dtype: float64

2. 描述统计:describe()
自动计算: 个数、均值、标准差、最小值、25%/50%/75% 分位数、最大值
-
代码
# 查看所有的描述性信息 s.describe()
-
结果

3. 缺失值判断:isna()
-
代码
# 获取元素的个数(不计缺失值) print(f"s.count():{s.count()}") # 获取索引 print(f"s.index:{s.index}") # 通过属性获取 print(f"s.keys():{s.keys()}") # 通过方法获取 # 判断是否为缺失值(如 NaN 或 None) s.isna() -
结果
``` s: a 77.0 b 32.0 c NaN d NaN e 54.0 f 12.0 g 77.0 ``` s.count():5 s.index:Index(['a', 'b', 'c', 'd', 'e', 'f', 'g'], dtype='str') s.keys():Index(['a', 'b', 'c', 'd', 'e', 'f', 'g'], dtype='str')

4. 包含判断:isin()
-
代码
# 判断元素是否包含在参数集合中 s.isin([10,66,32]) ``` s: a 77.0 b 32.0 c NaN d NaN e 54.0 f 12.0 g 77.0 ```
-
结果

5. 排序、去重:
-
代码
``` s: a 77.0 b 32.0 c NaN d NaN e 54.0 f 12.0 g 77.0 ``` # 按值排序 s.sort_values() # 去重 s.unique() # 返回去重后的list s.drop_duplicates() # 返回去重后的 Series,但不修改原 Series
-
结果
①按值排序:

②s.unique()
-
array([77., 32., nan, 54., 12.])
③s.drop_duplicates()

-
6. 相邻差值:diff()
后一个数 − 前一个数 → 取绝对值
-
代码
# 计算相邻元素之间的差值(一阶差分) s.diff().abs()
-
结果

7. 生成时间序列:pd.date_range()
-
基本语法:
pd.date_range(start=None, end=None, periods=None, freq=None, tz=None, normalize=False, name=None, closed=None)
| 参数 | 类型 | 默认值 | 说明 | 示例 |
|---|---|---|---|---|
| start | str/datetime | None | 起始日期 | '2026-01-01' |
| end | str/datetime | None | 结束日期 | '2026-12-31' |
| periods | int | None | 时间点数量 | 10, 100 |
| freq | str | 'D' | 频率 | 'D', 'ME', 'H' |
| tz | str | None | 时区 | 'UTC', 'Asia/Shanghai' |
| normalize | bool | False | 归一化到午夜 | True/False |
| name | str | None | 索引名称 | 'date', 'timestamp' |
| inclusive | str | None | 区间闭合 | 'left', 'right', None |
⚠️ 重要规则:必须提供以下组合之一
start + end + freq
start/end + periods + freq
start + periods + freq
end + periods + freq
-
常用频率别名(freq)
-
-
日期频率
频率代码 说明 示例输出 适用场景 'D'日历日 2026-01-01, 2026-01-02, ... 日度数据 'B'工作日(周一至周五) 2026-01-01(Thu), 2026-01-02(Fri), ... 股票交易、业务数据 'C'自定义工作日 需自定义 特殊工作日历
-
-
-
周频率
频率代码 说明 示例输出 适用场景 'W'或'W-SUN'每周日 2026-01-04, 2026-01-11, ... 周报 'W-MON'每周一 2026-01-05, 2026-01-12, ... 周报 'W-TUE'~'W-SAT'每周二~六 类似 周报
-
-
-
月频率
频率代码 说明 示例输出 适用场景 'MS'月初(1 号) 2026-01-01, 2026-02-01, ... 月报、预算 'ME'月末(最后一天) 2026-01-31, 2026-02-28, ... 月报、结算 'BMS'工作月初 2026-01-01(Thu), 2026-02-02(Mon), ... 业务月报 'BM'工作月末 2026-01-30(Fri), 2026-02-27(Fri), ... 业务结算
-
-
-
季度频率
频率代码 说明 示例输出 适用场景 'QS'季初(1/4/7/10 月 1 日) 2026-01-01, 2026-04-01, ... 季报 'QE'季末(3/6/9/12 月末日) 2026-03-31, 2026-06-30, ... 季报 'QS-MAR'财季初(3 月开始) 2026-03-01, 2026-06-01, ... 财年报表
-
-
-
年频率
频率代码 说明 示例输出 适用场景 'YS'或'AS'年初(1 月 1 日) 2026-01-01, 2027-01-01, ... 年报 'YE'或'A'年末(12 月 31 日) 2026-12-31, 2027-12-31, ... 年报 'YS-MAR'财年年初(3 月) 2026-03-01, 2027-03-01, ... 财年报表
-
-
-
时间频率
频率代码 说明 示例输出 适用场景 'H'小时 00:00, 01:00, 02:00, ... 小时数据 'T'或'min'分钟 00:00, 00:01, 00:02, ... 分钟数据 'S'秒 00:00:00, 00:00:01, ... 秒级数据 'L'或'ms'毫秒 00:00:00.000, ... 高频交易 'U'或'us'微秒 - 超高频数据
-
-
-
复合频率
频率代码 说明 示例 输出间隔 '2D'每 2 天 freq='2D'隔天 '3H'每 3 小时 freq='3H'3 小时间隔 '30T'每 30 分钟 freq='30T'半小时 '2W-MON'每 2 周周一 freq='2W-MON'双周 '3MS'每 3 个月初 freq='3MS'季度初
-
-
例子:
-
代码
import pandas as pd # 完整参数演示 dt_index = pd.date_range( start="2026-01-01", # 开始时间 end="2026-01-05", # 结束时间 periods=None, # 生成多少个(这里不用,因为 start+end 已确定) freq="D", # 按天生成 tz="Asia/Shanghai", # 时区:上海 normalize=True, # 统一归一到 00:00:00 name="my_date", # 给索引起名字 inclusive="left" # 包含左边界,不包含右边界 ) print(dt_index) -
结果
DatetimeIndex(['2026-01-01 00:00:00+08:00', '2026-01-02 00:00:00+08:00', '2026-01-03 00:00:00+08:00', '2026-01-04 00:00:00+08:00'], dtype='datetime64[us, Asia/Shanghai]', name='my_date', freq='D')
8. 重采样: resample()
-
代码
import pandas as pd import numpy as np np.random.seed(43) dates = pd.date_range('2026-01-01', '2026-12-31', freq='ME') # 12个月月末日期 # 生成12个随机销售数据 sales = pd.Series( np.random.randint(100, 1000, size=12), index=dates, name='sales') # 按【季度】重采样 → 求和 quarterly_sales = sales.resample('QS').sum() print(f"月度销售总额:\n{monthly_sales}") -
结果
月度销售总额: 2026-01-01 1711 2026-04-01 1452 2026-07-01 1280 2026-10-01 2224 Freq: QS-JAN, Name: sales, dtype: int32
9. 环比增长率:pct_change()
公式:今日增长率 = (今日值 - 昨日值)/ 昨日值
若结果为 正数 → 今日比昨日涨了
若结果为 负数 → 今日比昨日跌了
若结果为 0 → 和昨日持平
-
代码
import pandas as pd import numpy as np np.random.seed(43) dates = pd.date_range('2026-01-01', '2026-12-31', freq='ME') # 12个月月末日期 sales = pd.Series( np.random.randint(100, 1000, size=12), index=dates, name='sales') a = sales.pct_change() print(f"环比增长率a:\n{a}") -
代码
环比增长率a: 2026-01-31 NaN 2026-02-28 -0.551282 2026-03-31 -0.154762 2026-04-30 1.583099 2026-05-31 -0.588877 2026-06-30 -0.580902 2026-07-31 -0.265823 2026-08-31 2.508621 2026-09-30 0.859951 2026-10-31 -0.620872 2026-11-30 2.341463 2026-12-31 0.019812 Freq: ME, Name: sales, dtype: float64
10. 滚动窗口 :rolling()
-
代码
# 滚动窗口计算 a = sales.pct_change() b = a > 0 result = b[b.rolling(2).sum()==2].keys().tolist() print(f"\n连续增长2天的日期:\n{result}") -
结果
连续增长2天的日期: [Timestamp('2026-09-30 00:00:00'), Timestamp('2026-12-31 00:00:00')]
11. 随机抽样:sample()
11.1 语法:
Series.sample(
n=None, # 抽取的样本数量
frac=None, # 抽取的样本比例(0~1)
replace=False, # 是否有放回抽样(True=可重复抽,False=不重复)
weights=None, # 抽样权重(概率)
random_state=None, # 随机种子(固定结果)
axis=None, # 对Series无用,默认0
ignore_index=False # 是否重置索引
)
11.2 代码演示:
import pandas as pd
# 创建 Series
s = pd.Series([10, 20, 30, 40, 50, 60, 70, 80, 90, 100],
index=['a','b','c','d','e','f','g','h','i','j'],
name = 'test')
-
普通抽取
-
代码
print(f"原始数据s:\n{s}") print(f"s.sample():\n{s.sample()}") # 无参数 → 默认抽 1 条 print(f"s.sample(n=3):\n{s.sample(n=3)}") # 随机抽 3 条 -
结果
原始数据s: a 10 b 20 c 30 d 40 e 50 f 60 g 70 h 80 i 90 j 100 Name: test, dtype: int64 s.sample(): f 60 Name: test, dtype: int64 s.sample(n=3): j 100 a 10 g 70 Name: test, dtype: int64
-
按比例抽样 frac
frac=1 → 打乱所有数据(常用!)
-
代码
# 随机抽 30% 的数据 print(f"s.sample(frac=0.3):\n{s.sample(frac=0.3)}") -
结果
s.sample(frac=0.3): c 30 e 50 g 70 Name: test, dtype: int64
-
有放回抽样 replace=True
-
代码
# 抽 5 条,允许重复抽取同一条 print(f"s.sample(n=5, replace=True):\n{s.sample(n=5, replace=True)}") -
结果
s.sample(n=5, replace=True): a 10 b 20 a 10 f 60 b 20 Name: test, dtype: int64
-
固定随机结果 random_state(种子)
-
代码
# 固定随机结果,每次运行抽的都一样 print(f"s.sample(n=3, random_state=123):\n{s.sample(n=3, random_state=123)}") -
结果
s.sample(n=3, random_state=123): e 50 a 10 h 80 Name: test, dtype: int64
-
重置索引 ignore_index
-
代码
# 抽样后,索引从 0 重新编号 print(f"s.sample(n=3, ignore_index=True):\n{s.sample(n=3, ignore_index=True)}") -
结果
s.sample(n=3, ignore_index=True): 0 60 1 80 2 90 Name: test, dtype: int64
-
带权重抽样 weights(按概率抽)
给每条数据设置被抽中的概率
-
代码
# 权重越大,越容易被抽到 weights = [0.1, 0.1, 0.5, 0.05, 0.05, 0.05, 0.05, 0.05, 0.05, 0.0] s.sample(n=2, weights=weights, random_state=66)
-
结果

(二) DataFrame
1. DataFrame的创建
1.1 通过 Series 创建
-
代码
import pandas as pd import numpy as np # 通过 Series 创建 s1 = pd.Series([2,41,36,91,33]) s2 = pd.Series([14,45,23,77,69]) df = pd.DataFrame({"第一列":s1,"第二列":s2}) df -
结果

1.2 通过 dict 字典创建
-
代码
# 通过字典创建 df2 = pd.DataFrame( { "姓名":["张三","李四","王五","赵六","小七"], "年龄":[18,19,20,21,22], "成绩":[67.5,89.5,78.5,90.5,85.5], "性别":["男","女","男","女","男"], "班级":["1","2","3","4","5"] },index=[1,2,3,4,5],columns=["姓名","年龄","性别","班级","成绩"] ) print(df2) df2 -
结果
姓名 年龄 性别 班级 成绩 1 张三 18 男 1 67.5 2 李四 19 女 2 89.5 3 王五 20 男 3 78.5 4 赵六 21 女 4 90.5 5 小七 22 男 5 85.5

2. DataFrame的属性
| 属性 | 说明 | 属性 | 说明 |
|---|---|---|---|
| index | DataFrame 的行索引 | loc [] | 显式索引,按行列标签索引或切片 |
| values | DataFrame 的值 | iloc [] | 隐式索引,按行列位置索引或切片 |
| dtypes | DataFrame 的元素类型 | at [] | 使用行列标签访问单个元素 |
| shape | DataFrame 的形状 | iat [] | 使用行列位置访问单个元素 |
| ndim | DataFrame 的维度 | T | 行列转置 |
| size | DataFrame 的元素个数 | ||
| columns | DataFrame 的列标签 |
2.1 DataFrame 的常用属性
-
代码
import numpy as np import pandas as pd df = pd.DataFrame( { "姓名":["张三","李四","王五","赵六","小七"], "年龄":[18,19,20,21,22], "成绩":[67.5,89.5,78.5,90.5,85.5], "性别":["男","女","男","女","男"], "班级":["1","2","3","4","5"] },index=[1,2,3,4,5],columns=["姓名","年龄","性别","班级","成绩"] ) print(f"DataFrame 的行索引:\n{df.index}") # 行索引 → [1,2,3,4,5] print(f"DataFrame 的列标签:\n{df.columns}") # 列名 → ['姓名','年龄','性别','班级','成绩'] print(f"DataFrame 的值:\n{df.values}") # 所有数据 → 二维 numpy 数组 print(f"DataFrame 的元素类型:\n{df.dtypes}") # 每一列的数据类型(int、float、object) print(f"DataFrame 的形状:{df.shape}") # 表格形状 → (行数, 列数) → (5,5) print(f"DataFrame 的元素个数:{df.size}") # 总元素个数 → 5×5=25 print(f"DataFrame 的维度:{df.ndim}") # 维度 → DataFrame 一定是 2 维 print(f"DataFrame 的行列转置:\n{df.T}") # 行列转置(行变列、列变行) df.T -
结果
DataFrame 的行索引: Index([1, 2, 3, 4, 5], dtype='int64') DataFrame 的列标签: Index(['姓名', '年龄', '性别', '班级', '成绩'], dtype='str') DataFrame 的值: [['张三' 18 '男' '1' 67.5] ['李四' 19 '女' '2' 89.5] ['王五' 20 '男' '3' 78.5] ['赵六' 21 '女' '4' 90.5] ['小七' 22 '男' '5' 85.5]] DataFrame 的元素类型: 姓名 str 年龄 int64 性别 str 班级 str 成绩 float64 dtype: object DataFrame 的形状:(5, 5) DataFrame 的元素个数:25 DataFrame 的维度:2 DataFrame 的行列转置: 1 2 3 4 5 姓名 张三 李四 王五 赵六 小七 年龄 18 19 20 21 22 性别 男 女 男 女 男 班级 1 2 3 4 5 成绩 67.5 89.5 78.5 90.5 85.5
2.2 获取数据(loc /iloc/at /iat)
loc /at → 按标签索引(自定义行号、列名)
iloc /iat → 按位置索引(0,1,2…)
-
代码
# 获取元素 loc iloc at iat import numpy as np import pandas as pd df = pd.DataFrame( { "姓名":["张三","李四","王五","赵六","小七"], "年龄":[18,19,20,21,22], "成绩":[67.5,89.5,78.5,90.5,85.5], "性别":["男","女","男","女","男"], "班级":["1","2","3","4","5"] },index=[1,2,3,4,5],columns=["姓名","年龄","性别","班级","成绩"] )-
按行标签索引
-
代码
# 按行标签索引 print(f"DataFrame 的第 1 行(df.loc[1]):\n{df.loc[1]}") # 按行标签索引 print(f"DataFrame 的第 1 行(df.iloc[0]):\n{df.iloc[0]}") # 按行位置索引-
结果
DataFrame 的第 1 行(df.loc[1]): 姓名 张三 年龄 18 性别 男 班级 1 成绩 67.5 Name: 1, dtype: object DataFrame 的第 1 行(df.iloc[0]): 姓名 张三 年龄 18 性别 男 班级 1 成绩 67.5 Name: 1, dtype: object
-
按列标签索引
-
代码
# 按列标签索引 print(f"DataFrame 的第 1 列(df.loc[:,'姓名']):\n{df.loc[:,'姓名']}") # 按列标签索引 print(f"DataFrame 的第 1 列(df.iloc[:,0]):\n{df.iloc[:,0]}") # 按列位置索引-
结果
DataFrame 的第 1 列(df.loc[:,'姓名']): 1 张三 2 李四 3 王五 4 赵六 5 小七 Name: 姓名, dtype: str DataFrame 的第 1 列(df.iloc[:,0]): 1 张三 2 李四 3 王五 4 赵六 5 小七 Name: 姓名, dtype: str
-
单个元素索引
-
代码
# 单个元素索引 print(f"DataFrame 的第 3 行第 1 列(df.loc[3,'姓名']):{df.loc[3,'姓名']}") # 按行列标签索引单个元素 print(f"DataFrame 的第 3 行第 1 列(df.iloc[2,0]):{df.iloc[2,0]}") # 按行列位置索引单个元素 print(f"DataFrame 的第 3 行第 1 列(df.at[3,'姓名']):{df.at[3,'姓名']}")# 使用行列标签索引单个元素 print(f"DataFrame 的第 3 行第 1 列(df.iat[2,0]):{df.iat[2,0]}") # 使用行列位置索引单个元素-
结果
DataFrame 的第 3 行第 1 列(df.loc[3,'姓名']):王五 DataFrame 的第 3 行第 1 列(df.iloc[2,0]):王五 DataFrame 的第 3 行第 1 列(df.at[3,'姓名']):王五 DataFrame 的第 3 行第 1 列(df.iat[2,0]):王五
-
3. 访问 DataFrame 的数据
-
代码
# 获取单列数据 import numpy as np import pandas as pd df = pd.DataFrame( { "姓名":["张三","李四","王五","赵六","小七"], "年龄":[18,19,20,21,22], "成绩":[67.5,89.5,78.5,90.5,85.5], "性别":["男","女","男","女","男"], "班级":["1","2","3","4","5"] },index=[1,2,3,4,5],columns=["姓名","年龄","性别","班级","成绩"] ) print(f"DataFrame 的第 1 列(df['姓名']):\n{df['姓名']}") print(f"DataFrame 的第 1 列(df.姓名):\n{df.姓名}") # 获取多列数据 print(f"DataFrame 的第 1 列(df[['姓名','性别','成绩']]):\n{df[['姓名','性别','成绩']]}")
df[ ['姓名', '性别', '成绩'] ] = df + [ (索引) + ['姓名', '性别', '成绩'] (列名列表) + ] (结束索引)
| 写法 | 含义 | 返回类型 | 适用场景 |
|---|---|---|---|
| df ['姓名'] | 选取单列 | Series (一维数组) | 只需要处理一列数据时 |
| df [ ['姓名'] ] | 选取单列 | DataFrame (二维表格) | 需要保持表格格式时 |
| df [ ['姓名', '成绩'] ] | 选取多列 | DataFrame (二维表格) | 必须用双括号,因为要传入列表 |
-
结果
DataFrame 的第 1 列(df['姓名']): 1 张三 2 李四 3 王五 4 赵六 5 小七 Name: 姓名, dtype: str DataFrame 的第 1 列(df.姓名): 1 张三 2 李四 3 王五 4 赵六 5 小七 Name: 姓名, dtype: str DataFrame 的第 1 列(df[['姓名','性别','成绩']]): 姓名 性别 成绩 1 张三 男 67.5 2 李四 女 89.5 3 王五 男 78.5 4 赵六 女 90.5 5 小七 男 85.5
4. DataFrame的常用方法
| 方法 | 说明 | 方法 | 说明 |
|---|---|---|---|
head() |
查看前 n 行数据,默认 5 行 | value_counts() |
每个唯一值的出现次数 |
tail() |
查看后 n 行数据,默认 5 行 | count() |
非缺失值数量 |
isin() |
判断元素是否包含在参数集合中 | duplicated() |
是否重复 |
isna() |
判断是否为缺失值(如 NaN 或 None) | drop_duplicates() |
去除重复项 |
sum() |
求和,自动忽略缺失值 | sample() |
随机抽样 |
mean() |
平均值 | replace() |
替换值 |
min() |
最小值 | sort_index() |
按索引排序 |
max() |
最大值 | sort_values() |
按值排序 |
var() |
方差 | replace() |
替换值 |
std() |
标准差 | nlargest() |
返回某列最大的n条数据 |
median() |
中位数 | nsmallest() |
返回某列最小的n条数据 |
mode() |
众数(可返回多个) | ||
quantile(q) |
分位数,q 取 0~1 之间 | ||
describe() |
常见统计信息(count、mean、std、min、25%、50%、75%、max) |
4.1 快速预览数据(head() / tail())
默认值:
head()/tail()不加参数默认查看 5 行
-
代码
import numpy as np import pandas as pd df = pd.DataFrame( { "姓名":["张三","李四","王五","赵六","小七"], "年龄":[18,19,20,21,22], "成绩":[67.5,89.5,78.5,90.5,85.5], "性别":["男","女","男","女","男"], "班级":["1","2","3","4","5"] },index=[1,2,3,4,5],columns=["姓名","年龄","性别","班级","成绩"] ) # 查看部分数据 print(f"DataFrame 的前 3 行(df.head(3)):\n{df.head(3)}") print(f"DataFrame 的后 2 行(df.tail(2)):\n{df.tail(2)}") -
结果
DataFrame 的前 3 行(df.head(3)): 姓名 年龄 性别 班级 成绩 1 张三 18 男 1 67.5 2 李四 19 女 2 89.5 3 王五 20 男 3 78.5 DataFrame 的后 2 行(df.tail(2)): 姓名 年龄 性别 班级 成绩 4 赵六 21 女 4 90.5 5 小七 22 男 5 85.5
4.2 布尔索引
-
代码
# 单条件:筛选成绩大于80的行 print(f"DataFrame 中成绩大于 80 的行(df[df.成绩>80]):\n{df[df.成绩>80]}") # 多条件:成绩60~80之间(且) print(f"DataFrame 中成绩大于 60 且小于 80 的行(df[df.成绩<80]):\n{df[(df.成绩>60) & (df.成绩<80)]}") -
结果
DataFrame 中成绩大于 80 的行(df[df.成绩>80]): 姓名 年龄 性别 班级 成绩 2 李四 19 女 2 89.5 4 赵六 21 女 4 90.5 5 小七 22 男 5 85.5 DataFrame 中成绩大于 60 且小于 80 的行(df[df.成绩<80]): 姓名 年龄 性别 班级 成绩 1 张三 18 男 1 67.5 3 王五 20 男 3 78.5
4.3 isin() 精准匹配筛选
isin([列表]):匹配多个指定值(适合多选筛选)
-
代码
# df.isin(values) 判断元素是否包含在参数集合中 print(f"DataFrame 中性别为男的行(df.isin(['男'])):\n{df[df.性别.isin(['男'])]}") print(f"DataFrame 中性别为男的行(df[df.性别=='男']):\n{df[df.性别=='男']}") # 判断全表元素是否包含指定值(返回布尔值) df.isin(['赵六',67.5,22]) -
结果
DataFrame 中性别为男的行(df.isin(['男'])): 姓名 年龄 性别 班级 成绩 1 张三 18 男 1 67.5 3 王五 20 男 3 78.5 5 小七 22 男 5 85.5 DataFrame 中性别为男的行(df[df.性别=='男']): 姓名 年龄 性别 班级 成绩 1 张三 18 男 1 67.5 3 王五 20 男 3 78.5 5 小七 22 男 5 85.5

4.4 描述性统计 + 随机抽样
-
代码
# 常见统计信息 print(f"DataFrame 的统计信息(df.describe()):\n{df.describe()}") # 随机抽样:frac=0.5 抽取50%的数据 print(f"DataFrame 的随机抽样(df.sample(frac=0.5)):\n{df.sample(frac=0.5)}") -
结果
DataFrame 的统计信息(df.describe()): 年龄 成绩 count 5.000000 5.000000 mean 20.000000 82.300000 std 1.581139 9.523655 min 18.000000 67.500000 25% 19.000000 78.500000 50% 20.000000 85.500000 75% 21.000000 89.500000 max 22.000000 90.500000 DataFrame 的随机抽样(df.sample(frac=0.5)): 姓名 年龄 性别 班级 成绩 3 王五 20 男 3 78.5 2 李四 19 女 2 89.5
4.5 排序操作
-
代码
# 按索引排序 print(f"DataFrame 的按索引排序(df.sort_index()):\n{df.sort_index()}") # 按「成绩」列的值升序排序(从小到大) print(f"DataFrame 的按值排序(df.sort_values(by='成绩')):\n{df.sort_values(by='成绩')}") -
结果
DataFrame 的按索引排序(df.sort_index()): 姓名 年龄 性别 班级 成绩 1 张三 18 男 1 67.5 2 李四 19 女 2 89.5 3 王五 20 男 3 78.5 4 赵六 21 女 4 90.5 5 小七 22 男 5 85.5 DataFrame 的按值排序(df.sort_values(by='成绩')): 姓名 年龄 性别 班级 成绩 1 张三 18 男 1 67.5 3 王五 20 男 3 78.5 5 小七 22 男 5 85.5 2 李四 19 女 2 89.5 4 赵六 21 女 4 90.5
4.6 快速获取最值数据
-
结果
# 返回某列最大的n条数据 print(f"DataFrame 的返回‘成绩’列最大的2条数据(df.nlargest(2,'成绩')):\n{df.nlargest(2,'成绩')}") # 返回某列最小的n条数据 print(f"DataFrame 的返回‘成绩’列最小的2条数据(df.nsmallest(2,'成绩')):\n{df.nsmallest(2,'成绩')}") -
结果
DataFrame 的返回‘成绩’列最大的2条数据(df.nlargest(2,'成绩')): 姓名 年龄 性别 班级 成绩 4 赵六 21 女 4 90.5 2 李四 19 女 2 89.5 DataFrame 的返回‘成绩’列最小的2条数据(df.nsmallest(2,'成绩')): 姓名 年龄 性别 班级 成绩 1 张三 18 男 1 67.5 3 王五 20 男 3 78.5
(三) 数据分析
| 流程阶段 | 核心问题 / 任务 | 典型内容示例 |
|---|---|---|
| 数据收集 | 数据从哪里来? | 从业务数据库、API、日志文件、公开数据集等获取原始数据 |
| 数据清洗 | 处理脏数据 | 缺失值处理、错误数据修正、格式标准化、去重等 |
| 数据分析 | 从数据中提取信息、回答业务问题 | 统计(平均值、最大值、比例)、分组对比(如不同用户群体消费差异) |
| 数据可视化 | 直观呈现分析结果,传递结论 | 折线图(趋势)、柱状图(对比)、散点图(相关性)等,“一图胜千言” |
1.数据收集
1.1 csv 文件(也可以.txt文件)的读取与保存
-
代码
import pandas as pd df = pd.read_csv('employees.csv') print(df.tail()) print(df.salary.mean()) df = df.tail() df.to_csv('new.csv') -
结果
employee_id first_name last_name email phone_number job_id \ 102 202 Pat Fay PFAY 603.123.6666 MK_REP 103 203 Susan Mavris SMAVRIS 515.123.7777 HR_REP 104 204 Hermann Baer HBAER 515.123.8888 PR_REP 105 205 Shelley Higgins SHIGGINS 515.123.8080 AC_MGR 106 206 William Gietz WGIETZ 515.123.8181 AC_ACCOUNT salary commission_pct manager_id department_id 102 6000.0 NaN 201.0 20.0 103 6500.0 NaN 101.0 40.0 104 10000.0 NaN 101.0 70.0 105 12000.0 NaN 101.0 110.0 106 8300.0 NaN 205.0 110.0 6461.682242990654 -
读取 CSV (
pd.read_csv)import pandas as pd # 基础读取 df = pd.read_csv('data.csv') # 完整参数示例 df = pd.read_csv('data.csv', sep=',', # 分隔符(默认逗号) header=0, # 第几行作为表头(0表示第一行) index_col=None, # 是否指定索引列 usecols=['姓名','成绩'], # 只读取指定列 nrows=100, # 只读取前100行 encoding='utf-8', # 编码格式 na_values=['NA', '-'], # 将特定值识别为缺失值 dtype={'年龄': int}, # 指定列的数据类型 parse_dates=['日期'] # 将列解析为日期格式 ) -
写出 CSV (
df.to_csv)# 基础写入 df.to_csv('output.csv') # 完整参数示例 df.to_csv('output.csv', index=True, # 是否保存索引(默认True) sep=',', # 分隔符 header=True, # 是否保存表头 columns=['姓名','成绩'], # 只保存指定列 encoding='utf-8-sig', # 编码(utf-8-sig 防止Excel中文乱码) mode='w', # 'w'=覆盖,'a'=追加 float_format='%.2f', # 浮点数保留2位小数 na_rep='NaN' # 缺失值填充为什么 )
1.2 json 数据的读取与保存
pandas只能读取简单的json文件,不能读取嵌套的json文件
-
代码
import pandas as pd df = pd.read_json('data1.json') # 用json模块读取嵌套的json文件 import json with open('test.json', 'r', encoding='utf-8') as f: data = json.load(f) print(data) df = pd.DataFrame(data['users'])# 创建DataFrame df -
结果
{'users': [{'id': 1, 'name': '张三', 'age': 28, 'email': 'zhangsan@example.com', 'is_active': True, 'join_date': '2022-03-15'}, {'id': 2, 'name': '李四', 'age': 35, 'email': 'lisi@example.com', 'is_active': False, 'join_date': '2021-11-02'}, {'id': 3, 'name': '王五', 'age': 24, 'email': 'wangwu@example.com', 'is_active': True, 'join_date': '2023-01-20'}]}
-
读取 json
# 基础读取 df = pd.read_json('data.json') # 不同格式的 JSON # 1. 列式(columns) json_data = ''' { "姓名": {"0": "张三", "1": "李四"}, "成绩": {"0": 85, "1": 92} } ''' df = pd.read_json(json_data, orient='columns') # 2. 记录式(records)- 最常用 json_data = ''' [ {"姓名": "张三", "成绩": 85}, {"姓名": "李四", "成绩": 92} ] ''' df = pd.read_json(json_data, orient='records') # 3. 索引式(index) json_data = ''' { "0": {"姓名": "张三", "成绩": 85}, "1": {"姓名": "李四", "成绩": 92} } ''' df = pd.read_json(json_data, orient='index') -
写入 json
# 基础写入 df.to_json('output.json') # 指定格式 df.to_json('output.json', orient='records', force_ascii=False) # orient 参数详解 df.to_json('output.json', orient='records') # 列表格式(推荐) df.to_json('output.json', orient='columns') # 列式格式 df.to_json('output.json', orient='split') # 分割格式 df.to_json('output.json', orient='index') # 索引格式 # force_ascii=False:保留中文(不转义为Unicode)
1.3 Excel 文件的读取与保存
-
读取 Excel (
pd.read_excel)# 基础读取 df = pd.read_excel('data.xlsx') # 读取指定 sheet df = pd.read_excel('data.xlsx', sheet_name='Sheet1') # sheet_name=0 # 读取指定行/列 df = pd.read_excel('report.xlsx', usecols=['A', 'C', 'E']) # 读取所有 sheet(返回字典) all_sheets = pd.read_excel('data.xlsx', sheet_name=None) print(all_sheets.keys()) # 查看所有 sheet 名称 # 自定义列名 df = pd.read_excel('report.xlsx', header = None, name = ['name1','name2','name3'...]) # 完整参数 df = pd.read_excel('data.xlsx', sheet_name='Sheet1', header=0, index_col=None, usecols='A:C', # 只读取A到C列 skiprows=[0, 1, 2], # 跳过前3行 nrows=50, # 只读前50行 dtype={'成绩': float} ) -
写出 Excel (
df.to_excel)# 基础写入 df.to_excel('output.xlsx') # 指定 sheet 名称 df.to_excel('output.xlsx', sheet_name='成绩表') # 多个 DataFrame 写入不同 sheet with pd.ExcelWriter('multi_sheet.xlsx') as writer: df1.to_excel(writer, sheet_name='Sheet1') df2.to_excel(writer, sheet_name='Sheet2') df3.to_excel(writer, sheet_name='Sheet3') # 完整参数 df.to_excel('output.xlsx', sheet_name='数据', index=True, header=True, startrow=0, # 从第几行开始 startcol=0, # 从第几列开始 na_rep='缺失' # 缺失值的替换文本 )
2. 数据清洗
2.1 缺失值处理
1. 认识缺失值
✨ 缺失值的三种形式
np.nan:NumPy 缺失值(数值型)
None:Python 原生空值(对象型)
pd.NA:Pandas 统一缺失值(推荐)
-
代码
import pandas as pd import numpy as np # 创建含缺失值的 Series s = pd.Series([1, 2, np.nan, None, pd.NA]) # 创建含缺失值的 DataFrame df = pd.DataFrame( [[np.nan,pd.NA,2],[2,3,5],[None,4,6]], columns=['第1列','第2列','第3列'] ) print(f"s:\n{s}") print(f"df:\n{df}") -
结果
s: 0 1 1 2 2 NaN 3 None 4 <NA> dtype: object df: 第1列 第2列 第3列 0 NaN <NA> 2 1 2.0 3 5 2 NaN 4 6
2. 查看缺失值
返回布尔值:
True= 缺失,False= 非缺失; 进阶:df.isna().sum()统计每列缺失值个数。
-
代码
print(f"pd.isna(s):\n{pd.isna(s)}") # 等价于 print(s.isna()) print(f"pd.isna(df):\n{pd.isna(df)}") # 等价于 print(df.isna()) -
结果
pd.isna(s): 0 False 1 False 2 True 3 True 4 True dtype: bool pd.isna(df): 第1列 第2列 第3列 0 True True False 1 False False False 2 True False False
3. 删除缺失值(dropna)
核心参数:
axis=0(默认):删行;axis=1:删列
how='any'(默认):有缺失就删;how='all':全缺失才删
thresh=n:保留至少有 n 个非缺失值的行 / 列
subset=['列名']:只检查指定列
-
代码
print(f"原始s:\n{s}") print(f"s.dropna():\n{s.dropna()}") print('-'*20) print(f"原始df:\n{df}") print(f"df.dropna():\n{df.dropna()}") # 删除【任何】含缺失值的行 print(f"df.dropna(how='all'):\n{df.dropna(how='all')}") # 【全是缺失值】才删除该行 print(f"df.dropna(thresh=2):\n{df.dropna(thresh=2)}") # 该行至少有 2 个非缺失值才保留 print(f"df.dropna(axis=1):\n{df.dropna(axis=1)}") # 删除【含缺失值的列】 print(f"df.dropna(subset=['第1列']):\n{df.dropna(subset=['第1列'])}") # 如果某列有缺失值,则删除有缺失值的行 -
结果
原始s: 0 1 1 2 2 NaN 3 None 4 <NA> dtype: object s.dropna(): 0 1 1 2 dtype: object -------------------- 原始df: 第1列 第2列 第3列 0 NaN <NA> 2 1 2.0 3 5 2 NaN 4 6 df.dropna(): 第1列 第2列 第3列 1 2.0 3 5 df.dropna(how='all'): 第1列 第2列 第3列 0 NaN <NA> 2 1 2.0 3 5 2 NaN 4 6 df.dropna(thresh=2): 第1列 第2列 第3列 1 2.0 3 5 2 NaN 4 6 df.dropna(axis=1): 第3列 0 2 1 5 2 6 df.dropna(subset=['第1列']): 第1列 第2列 第3列 1 2.0 3 5
4. 填充缺失值(fillna)
填充策略选择:
数值列:均值、中位数、固定值
时间序列:前向 / 后向填充(
ffill/bfill)分类列:众数
-
代码
df = pd.read_csv('weather_withna.csv') print(f"df.tail():\n{df.tail()}") df.isna().sum(axis=0) df.head() print('-'*20) # 1. 固定值填充(指定列) print(f"1.固定值填充df.fillna('temp_max':20).tail()'):\n{df.fillna({'temp_max':20}).tail()}") # 2. 平均值填充 print(f"2.用平均值填充df.fillna(df[['wind']].mean()).tail():\n{df.fillna(df[['wind']].mean()).tail()}") # 3. 前向填充(用前一行的值填) print(f"3.用前一行填充df.ffill().tail():\n{df.ffill().tail()}") # 等价于 df.fillna(method='ffill') # 4. 后向填充(用后一行的值填) print(f"4.用后一行填充df.bfill().tail():\n{df.bfill().tail()}") # 等价于 df.fillna(method='bfill') -
结果
df.tail(): date precipitation temp_max temp_min wind weather 1456 2015-12-27 NaN NaN NaN NaN NaN 1457 2015-12-28 NaN NaN NaN NaN NaN 1458 2015-12-29 NaN NaN NaN NaN NaN 1459 2015-12-30 NaN NaN NaN NaN NaN 1460 2015-12-31 20.6 12.2 5.0 3.8 rain -------------------- 1.固定值填充df.fillna('temp_max':20).tail()'): date precipitation temp_max temp_min wind weather 1456 2015-12-27 NaN 20.0 NaN NaN NaN 1457 2015-12-28 NaN 20.0 NaN NaN NaN 1458 2015-12-29 NaN 20.0 NaN NaN NaN 1459 2015-12-30 NaN 20.0 NaN NaN NaN 1460 2015-12-31 20.6 12.2 5.0 3.8 rain 2.用平均值填充df.fillna(df[['wind']].mean()).tail(): date precipitation temp_max temp_min wind weather 1456 2015-12-27 NaN NaN NaN 3.242055 NaN 1457 2015-12-28 NaN NaN NaN 3.242055 NaN 1458 2015-12-29 NaN NaN NaN 3.242055 NaN 1459 2015-12-30 NaN NaN NaN 3.242055 NaN 1460 2015-12-31 20.6 12.2 5.0 3.800000 rain 3.用前一行填充df.ffill().tail(): date precipitation temp_max temp_min wind weather 1456 2015-12-27 0.0 11.1 4.4 4.8 sun 1457 2015-12-28 0.0 11.1 4.4 4.8 sun 1458 2015-12-29 0.0 11.1 4.4 4.8 sun 1459 2015-12-30 0.0 11.1 4.4 4.8 sun 1460 2015-12-31 20.6 12.2 5.0 3.8 rain 4.用后一行填充df.bfill().tail(): date precipitation temp_max temp_min wind weather 1456 2015-12-27 20.6 12.2 5.0 3.8 rain 1457 2015-12-28 20.6 12.2 5.0 3.8 rain 1458 2015-12-29 20.6 12.2 5.0 3.8 rain 1459 2015-12-30 20.6 12.2 5.0 3.8 rain 1460 2015-12-31 20.6 12.2 5.0 3.8 rain
2.2 重复数据处理
1. 标记重复值
返回布尔值:
True= 重复行(默认保留第一次出现的)
-
代码
import pandas as pd data = { "name":['alice','alice','bob','alice','jack','bob'], "age":[26,25,30,25,35,30], 'city':['NY','NY','LA','NY','SF','LA'] } df = pd.DataFrame(data) df print(f"df.duplicated():\n{df.duplicated()}") # 整行数据都是一样的,标记为重复,返回True -
结果
df:

df.duplicated(): 0 False 1 False 2 False 3 True 4 False 5 True dtype: bool
2. 删除重复值
核心参数:
subset=['列名']:指定去重依据的列
keep='first'(默认):保留第一次;keep='last':保留最后一次;keep=False:删除所有重复
-
代码
print(f"原始数据:\n{pd.DataFrame(data)}") print('-'*20) # 整行完全重复才删除 print(f"df.drop_duplicates():\n{df.drop_duplicates()}") print('-'*20) # 只看【name列】,重复就删 print(f"df.drop_duplicates(subset=['name']):\n{df.drop_duplicates(subset=['name'])}") print('-'*20) # 保留【最后一次】出现的 print(f"df.drop_duplicates(subset=['name'],keep='last'):\n{df.drop_duplicates(subset=['name'],keep='last')}") -
结果
原始数据: name age city 0 alice 26 NY 1 alice 25 NY 2 bob 30 LA 3 alice 25 NY 4 jack 35 SF 5 bob 30 LA -------------------- df.drop_duplicates(): name age city 0 alice 26 NY 1 alice 25 NY 2 bob 30 LA 4 jack 35 SF -------------------- df.drop_duplicates(subset=['name']): name age city 0 alice 26 NY 2 bob 30 LA 4 jack 35 SF -------------------- df.drop_duplicates(subset=['name'],keep='last'): name age city 3 alice 25 NY 4 jack 35 SF 5 bob 30 LA
2.3 数据类型转换
常用类型:
int/int16/int32:整数(节省内存用小类型)
float:浮点数
str/object:字符串
datetime64:日期时间(需用pd.to_datetime())
-
代码
df = pd.read_csv('sleep.csv') print(f"转换前的数据类型df.dtypes:\n{df.dtypes}") print('-'*20) df['age'] = df['age'].astype('int16') print(f"转换后的age的数据类型:\n{df['age'].dtype}") -
结果
转换前的数据类型df.dtypes: person_id int64 gender str age int64 occupation str sleep_duration float64 sleep_quality float64 physical_activity_level int64 stress_level int64 bmi_category str blood_pressure str heart_rate int64 daily_steps int64 sleep_disorder str dtype: object -------------------- 转换后的age的数据类型: int16
2.4 数据变形(宽表 ↔ 长表)
1. 转置(行列互换)
-
代码
import pandas as pd data = { 'ID':[1,2], 'name':['alice','bob'], 'Math':[90,85], 'English':[88,92], 'Science':[95,89] } df = pd.DataFrame(data) print(f"原始数据:\n{df}") print('-'*20) print(f"df.T转置:\n{df.T}") -
结果
原始数据: ID name Math English Science 0 1 alice 90 88 95 1 2 bob 85 92 89 -------------------- df.T转置: 0 1 ID 1 2 name alice bob Math 90 85 English 88 92 Science 95 89
2. 宽表转长表(melt)
-
代码
print('-'*10,'宽表转长表','-'*10) df2 = pd.melt(df,id_vars=['ID','name'], var_name='科目', value_name='分数') print(f"宽表转长表df2:\n{df2}") print('-'*10,'排序','-'*10) print(f"df2.sort_values('name'):\n{df2.sort_values('name')}") -
结果
''' 原始数据: ID name Math English Science 0 1 alice 90 88 95 1 2 bob 85 92 89 ''' ---------- 宽表转长表 ---------- 宽表转长表df2: ID name 科目 分数 0 1 alice Math 90 1 2 bob Math 85 2 1 alice English 88 3 2 bob English 92 4 1 alice Science 95 5 2 bob Science 89 ---------- 排序 ---------- df2.sort_values('name'): ID name 科目 分数 0 1 alice Math 90 2 1 alice English 88 4 1 alice Science 95 1 2 bob Math 85 3 2 bob English 92 5 2 bob Science 89
3. 长表转宽表(pivot)
-
代码
# 长表转宽表 print('-'*10,'长表转宽表','-'*10) df3 = pd.pivot(df2, index=['ID','name'], columns='科目', values='分数') print(f"长表转宽表df3:\n{df3}") df3 -
结果
---------- 长表转宽表 ---------- 长表转宽表df3: 科目 English Math Science ID name 1 alice 88 90 95 2 bob 92 85 89

3. 数据分析
3.1 文本分列(str.split)
关键参数详解:
str.split(" "):按空格分割字符串
expand=True:必须加! 返回 DataFrame(多列),否则返回 Series(列表)左边
[['first','last']]:给拆分后的两列命名
-
代码
import pandas as pd data = { 'ID':[1,2], 'name':['alice smith','bob smith'], 'Math':[90,85], 'English':[88,92], 'Science':[95,89] } df = pd.DataFrame(data) # 原始数据 # 原始数据:name列是"名 姓"格式 print(f"原始数据:\n{df}") # 1. 分列 print('-'*10,'分列','-'*10) df[['first','last']] = df['name'].str.split(" ",expand= True) print(f"分列后的数据:\n{df}") -
结果
原始数据: ID name Math English Science 0 1 alice smith 90 88 95 1 2 bob smith 85 92 89 ---------- 分列 ---------- 分列后的数据: ID name Math English Science first last 0 1 alice smith 90 88 95 alice smith 1 2 bob smith 85 92 89 bob smith
3.2 数据分箱(连续数据离散化)
核心作用:把连续的数值型数据(如工资、年龄、成绩)转换成离散的分类数据(如低 / 中 / 高薪),方便统计分析和建模。
Pandas 提供两种分箱方法:
pd.cut():等宽分箱(区间宽度相同)
pd.qcut():等频分箱(每个区间数据量相同)
1. pd.cut() 等宽分箱
用法 1:自动等分区间
自动计算最小值和最大值
平均划分区间
区间格式:
(a, b](左开右闭,包含 b 不包含 a)
-
代码
import pandas as pd df = pd.read_csv('employees.csv') df1 = df.head(10)[['employee_id','salary']] df1 # bins = n,将连续数值划分为等宽的区间 pd.cut(df1['salary'],bins=2) # 1.自动计算范围:找到 salary 的最小值(4200)和最大值(24000) # 2.等分区间:将整个范围平均分成 2 个区间 # 区间1:(4180.2, 14100.0] - 低薪组 # 区间2:(14100.0, 24000.0] - 高薪组 # 3.分类标记:每个工资值被分配到对应的区间 # 4.区间表示法:(a, b] 表示左开右闭,即 a < x ≤ b # 5.边界扩展:Pandas 自动向外扩展 0.1%,确保所有数据都能被归类 -
结果
原始数据:

自动等分2个区间:

用法 2:统计每个区间的数量
-
代码
pd.cut(df1['salary'],bins=2).value_counts()
-
结果

用法 3:自定义区间(最常用)
-
代码1
pd.cut(df1['salary'],bins=[0,10000,20000,30000]).value_counts()

-
代码2:添加自定义标签
pd.cut(df1['salary'], bins=[0,10000,20000,30000], labels=['低薪组','中薪组','高薪组']).value_counts()
-
代码3:将分箱结果保存为新列
df1['收入范围'] = pd.cut(df1['salary'], bins=[0,10000,20000,30000], labels=['低薪组','中薪组','高薪组']) df1
2. pd.qcut() 等频分箱
解决
pd.cut()数据分布不均的问题适合数据偏斜严重的场景(如工资、房价)
-
代码
# 把工资分成 3 个区间,每个区间人数大致相等 pd.qcut(df1['salary'],3).value_counts()
-
结果

3.3 索引操作
索引是 DataFrame 的 "身份证",合理设置索引可以大幅提升数据查询和操作的效率
1. 设置索引(set_index)
原来的 ' 姓名 ' 列会变成行索引
推荐写法:
df_new = df.set_index('姓名')(不修改原数据)不推荐:
df.set_index('姓名', inplace=True)(直接修改原数据,容易出错)
-
代码
import pandas as pd df = pd.DataFrame({ '姓名': ['张三', '李四', '王五'], '年龄': [18, 19, 20], '成绩': [85, 90, 78] }) df_new = df.set_index('姓名') print(df_new) -
结果
年龄 成绩 姓名 张三 18 85 李四 19 90 王五 20 78
2. 重置索引(reset_index)
行索引会变成名为 'index' 的普通列
如果原来的索引是自定义的(如姓名),会变回原来的列
-
代码
df_reset = df_new.reset_index() print(df_reset)
-
结果
姓名 年龄 成绩 0 张三 18 85 1 李四 19 90 2 王五 20 78
3.4 时间数据处理
Pandas 对时间数据的支持极其强大,可以轻松完成日期解析、提取、计算、切片等操作
1. 认识 Timestamp 对象
-
代码1:常用属性
import pandas as pd d = pd.Timestamp('2026-05-07 22:39:56') print(d) # 属性 print('-'*20,'属性','-'*20) print("年:",d.year) print("月:",d.month) print("日:",d.day) print("小时:",d.hour) print("分钟:",d.minute) print("秒:",d.second) print("季度:",d.quarter) -
结果
2026-05-07 22:39:56 -------------------- 属性 -------------------- 年: 2026 月: 5 日: 7 小时: 22 分钟: 39 秒: 56 季度: 2
-
代码2:常用方法
# 方法 print('-'*20,'方法','-'*20) print("星期几:",d.day_name()) print("是周几:",d.day_of_week) print("转换为季度:",d.to_period('Q')) print("转换为年度:",d.to_period('Y')) print("转换为月度:",d.to_period('M')) -
结果
-------------------- 方法 -------------------- 星期几: Thursday 是周几: 3 转换为季度: 2026Q2 转换为年度: 2026 转换为月度: 2026-05
2. 字符串转日期(pd.to_datetime)
-
代码1:单个字符串转日期
import pandas as pd a = pd.to_datetime('2026-05-07 22:39:56') print(a) print(type(a)) -
结果
2026-05-07 22:39:56 <class 'pandas.Timestamp'>
-
代码2:DataFrame 列转日期
df = pd.DataFrame({ 'sales':[100,200,30], 'date':['20260507','20260508','20260509'] }) df['datetime'] = pd.to_datetime(df['date']) print(df) -
结果
sales date datetime 0 100 20260507 2026-05-07 1 200 20260508 2026-05-08 2 30 20260509 2026-05-09
-
代码3:读取 CSV 时直接解析日期
在读取 CSV 文件时,自动将指定列转换为 datetime 类型,避免后续手动转换。
df = pd.read_csv('weather.csv',parse_dates=['date']) df.info() -
结果
<class 'pandas.DataFrame'> RangeIndex: 1461 entries, 0 to 1460 Data columns (total 6 columns): # Column Non-Null Count Dtype --- ------ -------------- ----- 0 date 1461 non-null datetime64[us] 1 precipitation 1461 non-null float64 2 temp_max 1461 non-null float64 3 temp_min 1461 non-null float64 4 wind 1461 non-null float64 5 weather 1461 non-null str dtypes: datetime64[us](1), float64(4), str(1) memory usage: 68.6 KB
3. dt 访问器
从日期列中提取年 / 月 / 日等信息,必须加
.dt.
-
代码
print('-'*20,'week','-'*20) df['week'] = df['datetime'].dt.day_name()#要添加.dt. print(df) print('-'*20,'year','-'*20) df['year'] = df['datetime'].dt.to_period('Y') print(df) print('-'*20,'month','-'*20) df['month'] = df['datetime'].dt.to_period('M') print(df) -
结果
-------------------- week -------------------- sales date datetime week 0 100 20260507 2026-05-07 Thursday 1 200 20260508 2026-05-08 Friday 2 30 20260509 2026-05-09 Saturday -------------------- year -------------------- sales date datetime week year 0 100 20260507 2026-05-07 Thursday 2026 1 200 20260508 2026-05-08 Friday 2026 2 30 20260509 2026-05-09 Saturday 2026 -------------------- month -------------------- sales date datetime week year month 0 100 20260507 2026-05-07 Thursday 2026 2026-05 1 200 20260508 2026-05-08 Friday 2026 2026-05 2 30 20260509 2026-05-09 Saturday 2026 2026-05
4. 日期作为索引 + 切片
支持多种日期格式:
"20130101"、"2013-01"、"2013"切片是闭区间(包含开始和结束日期)
-
代码
# 设置日期为索引/设置原来的df为索引 df.set_index('date',inplace=True) # 日期切片 print(df.loc["20130101":"20130105"]) -
结果
precipitation temp_max temp_min wind weather date 2013-01-01 0.0 5.0 -2.8 2.7 sun 2013-01-02 0.0 6.1 -1.1 3.2 sun 2013-01-03 4.1 6.7 -1.7 3.0 rain 2013-01-04 2.5 10.0 2.2 2.8 rain 2013-01-05 3.0 6.7 4.4 3.1 rain
5. 时间间隔计算
-
代码
import pandas as pd d1 = pd.Timestamp('2026-05-07 22:39:56') d2 = pd.Timestamp('2026-08-08 00:39:56') print(d2-d1) print('-'*20) df = pd.read_csv('weather.csv',parse_dates=['date']) # 计算每条记录与第一天的时间间隔 df['delta'] = df['date'] - df['date'][0] # 与第一天时间的间隔 print(df) -
结果
92 days 02:00:00 -------------------- date precipitation temp_max temp_min wind weather delta 0 2012-01-01 0.0 12.8 5.0 4.7 drizzle 0 days 1 2012-01-02 10.9 10.6 2.8 4.5 rain 1 days 2 2012-01-03 0.8 11.7 7.2 2.3 rain 2 days 3 2012-01-04 20.3 12.2 5.6 4.7 rain 3 days 4 2012-01-05 1.3 8.9 2.8 6.1 rain 4 days ... ... ... ... ... ... ... ... 1456 2015-12-27 8.6 4.4 1.7 2.9 rain 1456 days 1457 2015-12-28 1.5 5.0 1.7 1.3 rain 1457 days 1458 2015-12-29 0.0 7.2 0.6 2.6 fog 1458 days 1459 2015-12-30 0.0 5.6 -1.0 3.4 sun 1459 days 1460 2015-12-31 0.0 5.6 -2.1 3.5 sun 1460 days [1461 rows x 7 columns]
3.5 分组聚合
核心作用: "先分组,再统计",是数据分析最常用的模式。比如:
按部门分组,计算平均工资
按月份分组,计算总销售额
按性别分组,计算平均年龄
1. 基础语法
df.groupby('分组列')['聚合列'].聚合函数()
-
单字段分组聚合
import pandas as pd df = pd.read_csv('employees.csv') df = df.dropna(subset=['department_id']) # 去除'department_id'列有缺失值的行 df['department_id'] = df['department_id'].astype('int64') # 按部门分组,计算平均工资 print('-'*20,'分组聚合(单个条件)','-'*20) df2 = df.groupby('department_id')[['salary']].mean() # 保留salary的小数点后两位 df2['salary'] = df2['salary'].round(2) print(f"df2.reset_index():\n{df2.reset_index()}")-------------------- 分组聚合(单个条件) -------------------- df2.reset_index(): department_id salary 0 10 4400.00 1 20 9500.00 2 30 4150.00 3 40 6500.00 4 50 3475.56 5 60 5760.00 6 70 10000.00 7 80 8955.88 8 90 19333.33 9 100 8600.00 10 110 10150.00 -
多字段分组聚合
# 按部门+职位分组,计算平均工资 print('-'*20,'分组聚合(多个条件)','-'*20) df2 = df.groupby(['department_id','job_id'])[['salary']].mean() # 保留salary的小数点后两位 df2['salary'] = df2['salary'].round(2) print(f"df2.reset_index():\n{df2.reset_index()}")-------------------- 分组聚合(多个条件) -------------------- df2.reset_index(): department_id job_id salary 0 10 AD_ASST 4400.00 1 20 MK_MAN 13000.00 2 20 MK_REP 6000.00 3 30 PU_CLERK 2780.00 4 30 PU_MAN 11000.00 5 40 HR_REP 6500.00 6 50 SH_CLERK 3215.00 7 50 ST_CLERK 2785.00 8 50 ST_MAN 7280.00 9 60 IT_PROG 5760.00 10 70 PR_REP 10000.00 11 80 SA_MAN 12200.00 12 80 SA_REP 8396.55 13 90 AD_PRES 24000.00 14 90 AD_VP 17000.00 15 100 FI_ACCOUNT 7920.00 16 100 FI_MGR 12000.00 17 110 AC_ACCOUNT 8300.00 18 110 AC_MGR 12000.00
2. 查看分组详情
-
代码
# 查看所有分组 print('-'*20,'查看所有分组','-'*20) print(df.groupby('department_id').groups) # 查看某个具体分组的数据 print('-'*20,'查看具体的某个分组数据','-'*20) print(df.groupby('department_id').get_group(20)) -
结果
-------------------- 查看所有分组 -------------------- {10: [100], 20: [101, 102], 30: [14, 15, 16, 17, 18, 19], 40: [103], 50: [20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99], 60: [3, 4, 5, 6, 7], 70: [104], 80: [45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 79], 90: [0, 1, 2], 100: [8, 9, 10, 11, 12, 13], 110: [105, 106]} -------------------- 查看具体的某个分组数据 -------------------- employee_id first_name last_name email phone_number job_id \ 101 201 Michael Hartstein MHARTSTE 515.123.5555 MK_MAN 102 202 Pat Fay PFAY 603.123.6666 MK_REP salary commission_pct manager_id department_id 101 13000.0 NaN 100.0 20 102 6000.0 NaN 201.0 20
3. 高级聚合(agg 方法)
df.groupby(by=['列名1','列名2']).agg({'列名1':'函数1','列名2':'函数2'})
-
代码
# 对不同列应用不同的聚合函数 # 按部门分组,计算: # - 员工人数 # - 平均工资 # - 最高工资 df.groupby('department_id').agg({ 'employee_id': 'count', 'salary': ['mean', 'max'] })
三、数据可视化
(一)matplotlib
| 图表类型 | 函数 | 核心用途 |
|---|---|---|
| 折线图 | plt.plot() |
趋势变化 |
| 柱状图 | plt.bar() |
分类垂直对比 |
| 条形图 | plt.barh() |
分类水平对比 |
| 饼图 / 环形图 | plt.pie() |
占比分析 |
| 散点图 | plt.scatter() |
变量相关性 |
| 箱线图 | plt.boxplot() |
分布 + 异常值 |
| 多子图 | plt.subplot() |
多图组合展示 |
| 直方图 | plt.hist() |
频数分布 |
1. 单个图表绘制
1.1 折线图 plt.plot()
关键参数:
linestyle='--':虚线;'-':实线
marker='o':数据点标记(圆圈 / 方块 / 三角)
plt.text():给数据点添加数值标注
-
代码
核心用途:展示数据随时间 / 序列的变化趋势(如销售额、气温、股价)
# 通用基础配置(所有绘图必写) import matplotlib.pyplot as plt from matplotlib import rcParams # 字体 rcParams['font.sans-serif'] = ['Microsoft YaHei'] # 设置字体 # 创建图表,设置大小 plt.figure(figsize=(10,5)) # 设置图表大小 # 绘图数据 month = ['1月','2月','3月','4月'] sales = [100,50,80,20] # 绘制折线图 plt.plot(month,sales, label='产品A', color='blue', linewidth=2, linestyle='--', marker='o') # 添加标题 plt.title('2026年销售趋势',color = 'red', fontsize = 20) # 标题颜色,标题大小 # 添加标签 plt.xlabel('月份',fontsize=10) # X轴标签 plt.ylabel('销售额(万元)',fontsize=10) # Y轴标签 # 添加图例(两种方法) plt.legend(['产品A'],loc = 'upper left') # 添加网格线 # plt.grid(True)# 显示所有网格线 # plt.grid(axis='y')# 只显示Y轴 # plt.grid(axis='x')# 只显示X轴 plt.grid(True,alpha=0.3,color='blue',linestyle='--')# 设置网格线,透明度,颜色,线型 # 设置刻度字体大小 plt.xticks(rotation=45,fontsize=10)# x轴旋转角度,刻度字体大小 plt.yticks(rotation=0,fontsize=10)# y轴旋转角度,刻度字体大小 # 设置y轴范围 plt.ylim(0,120) # 在每个数据点上显示数据 for x,y in zip(month,sales): plt.text(x,y+2,str(y),ha='center',va='bottom',fontsize=10) # 自动优化图形 plt.tight_layout() # 显示图表 plt.show()
1.2 柱状图 plt.bar()
核心用途:分类数据的大小对比(垂直柱子,如各科成绩、各产品销量)
特点:适合类别少、对比清晰的场景。
-
代码
import matplotlib.pyplot as plt from matplotlib import rcParams # 字体 rcParams['font.sans-serif'] = ['Microsoft YaHei'] # 设置字体 # 创建图表,设置大小 plt.figure(figsize=(10,5)) # 设置图表大小 # 绘图数据 subjects = ['语文','数学','英语','物理','化学','生物'] scores = [80,91,73,66,82,99] # 绘制柱状图 plt.bar(subjects,scores, color='blue', width=0.5, alpha=0.5) # 添加标题 plt.title('2026年考试成绩',color = 'red', fontsize = 20) # 添加标签 plt.xlabel('课程',fontsize=10) plt.ylabel('分数',fontsize=10) # 添加图例 plt.legend(['小明'],loc = 'upper left') # 添加网格线 plt.grid(axis='y',alpha=0.1,color='blue',linestyle='--') # 添加刻度字体大小 plt.xticks(rotation=45,fontsize=10) plt.yticks(rotation=0,fontsize=10) # 在每个数据点上显示数据 for x,y in zip(subjects,scores): plt.text(x,y+2,str(y),ha='center',va='bottom',fontsize=10) # 添加y轴范围 plt.ylim(0,100) # 自动优化图形 plt.tight_layout() # 显示图表 plt.show()
1.3 条形图 plt.barh()
核心用途:水平分类对比(如国家 GDP、排名类数据)
区别:柱状图垂直,条形图水平;类别名长时优先用条形图。
-
代码
import matplotlib.pyplot as plt from matplotlib import rcParams # 字体 rcParams['font.sans-serif'] = ['Microsoft YaHei'] # 设置字体 # 创建图表,设置大小 plt.figure(figsize=(10,5)) # 设置图表大小 # 绘图数据 countries = ['中国','美国','日本','印度','法国','英国'] GDP = [1389, 1871, 1269, 1085, 1085, 1025] # 绘制条形图 plt.barh(countries,GDP, color='blue', height=0.5, alpha=0.5) # 添加标题 plt.title('2026年GDP排名',color = 'red', fontsize = 20) # 添加标签 plt.xlabel('GDP(亿美元)',fontsize=10) plt.ylabel('国家',fontsize=10) # 添加图例 plt.legend(['GDP'],loc = 'upper right') # 添加网格线 plt.grid(axis='x',alpha=0.1,color='blue',linestyle='--') # 添加刻度字体大小 plt.xticks(rotation=0,fontsize=10) plt.yticks(rotation=0,fontsize=10) # 在每个数据点上显示数据 for x,y in zip(countries,GDP): plt.text(y+50,x,str(y),ha='center',va='bottom',fontsize=10) # 添加y轴范围 plt.xlim(0,2000) # 自动优化图形 plt.tight_layout() # 显示图像 plt.show()
1.4 饼图 / 环形图 plt.pie()
核心用途:展示各部分占总体的比例(如时间分配、收支占比) 关键参数:
autopct='%1.2f%%':保留 2 位小数的百分比
explode=[0.1,0,0]:突出显示某一块扇形
-
饼图代码
import matplotlib.pyplot as plt from matplotlib import rcParams # 字体 rcParams['font.sans-serif'] = ['Microsoft YaHei'] # 设置字体 # 创建图表,设置大小 plt.figure(figsize=(10,5)) # 设置图表大小 # 绘图数据 things = ['学习','娱乐','运动','睡觉','其他'] times = [6,4,1,8,5] # 配色方案 colors = ['#66b3ff', '#99ff99', '#ffcc99', '#ff9999', '#ff4499'] # 设置饼图分离 explode=[0.1,0,0,0,0] plt.pie(times, labels=things, autopct='%1.2f%%', colors=colors, # 颜色 explode=explode,# 设置饼图分离 shadow=True,# 添加阴影 startangle=0) # 添加标题 plt.title('一天的时间分布',color = 'red', fontsize = 20) # 自动优化图形 plt.tight_layout() # 显示图像 plt.show()
-
环形饼图代码
import matplotlib.pyplot as plt from matplotlib import rcParams # 字体 rcParams['font.sans-serif'] = ['Microsoft YaHei'] # 设置字体 # 创建图表,设置大小 plt.figure(figsize=(10,5)) # 设置图表大小 # 绘图数据 things = ['学习','娱乐','运动','睡觉','其他'] times = [6,4,1,8,5] # 配色方案 colors = ['#66b3ff', '#99ff99', '#ffcc99', '#ff9999', '#ff4499'] plt.pie(times, labels=things, autopct='%1.2f%%', colors=colors, # 颜色 wedgeprops={'width': 0.6},# 设置圆环宽度(环形饼图) pctdistance=0.5,# 百分比距离 explode=[0.1,0,0,0,0],# 设置饼图分离 shadow=True,# 添加阴影 startangle=0) # 添加标题 plt.title('一天的时间分布',color = 'red', fontsize = 20) plt.text(0, 0, '一天中\n时间分布', color='red', fontsize=15, ha='center', va='center') # 自动优化图形 plt.tight_layout() # 显示图像 plt.show()
1.5 散点图 plt.scatter()
核心用途:展示两个变量之间的相关性(如身高体重、广告投入 vs 销量)
特点:一眼看出数据是正相关 / 负相关 / 无相关。
-
代码
import matplotlib.pyplot as plt from matplotlib import rcParams # 字体 import random rcParams['font.sans-serif'] = ['Microsoft YaHei'] # 设置字体 # 创建图表,设置大小 plt.figure(figsize=(10,7)) # 设置图表大小 # 绘图数据 x = [] y = [] for i in range(500): temp = random.randint(1,100) x.append(temp) y.append(2*temp + random.randint(0,100)) # 绘制折线图 plt.scatter(x,y, color='blue', alpha=0.5, s=20 # 散点大小 ) # 添加标题 plt.title('X与Y变量的关系',color = 'red', fontsize = 20) # 标题颜色,标题大小 # 添加标签 plt.xlabel('X自变量',fontsize=10) # X轴标签 plt.ylabel('Y因变量',fontsize=10) # Y轴标签 # 添加图例(两种方法) plt.legend(['数据'],loc = 'upper left') # 添加网格线 plt.grid(True,alpha=0.3,color='blue',linestyle='--')# 设置网格线,透明度,颜色,线型 # 设置刻度字体大小 plt.xticks(rotation=45,fontsize=10)# x轴旋转角度,刻度字体大小 plt.yticks(rotation=0,fontsize=10)# y轴旋转角度,刻度字体大小 # 回归线 plt.plot([0,100],[50,250],color='red') plt.text(50, 200, '回归线', color='red', fontsize=15, ha='center', va='center') # 自动优化图形 plt.tight_layout() # 显示图表 plt.show()
1.6 箱线图 plt.boxplot()
核心用途:展示数据分布、离散程度、异常值(如成绩分布、工资分布)
解读:箱子 = 中位数 + 四分位数,须线 = 正常范围,圆点 = 异常值。

-
代码
import matplotlib.pyplot as plt from matplotlib import rcParams # 字体 rcParams['font.sans-serif'] = ['Microsoft YaHei'] # 设置字体 # 模拟3门课的成绩 data = { '语文':[82,85,88,70,90,76,84,83,95], '数学':[75,80,79,93,88,82,87,89,92], '英语':[70,72,68,65,78,80,85,90,95] } # 绘制图表大小 plt.figure(figsize=(8,6)) # 绘制箱线图 plt.boxplot(data.values(),tick_labels=list(data.keys())) # 添加标题 plt.title('课程成绩箱线图',color = 'red', fontsize = 20) # 添加标签 plt.xlabel('课程',fontsize=10,color='blue') plt.ylabel('分数',fontsize=10,color='blue') # 添加网格线 plt.grid(axis='y',alpha=0.3,color='blue',linestyle='--') # 自动优化图形 plt.tight_layout() # 显示图表 plt.show()
2. 多个图表绘制(子图 subplot)
核心用途:在一张画布上画多个子图,对比展示数据
# 语法:plt.subplot(总行数, 总列数, 当前子图位置) plt.subplot(2,2,1) # 2行2列,第1个子图 plt.plot() plt.subplot(2,2,2) # 第2个子图 plt.bar() plt.tight_layout() # 自动调整子图间距,不重叠 plt.show()
-
代码
import matplotlib.pyplot as plt from matplotlib import rcParams # 字体 rcParams['font.sans-serif'] = ['Microsoft YaHei'] # 设置字体 # 绘图数据 months = ['1月','2月','3月','4月'] sales = [100,189,125,200] # 创建图表,设置大小 f1 = plt.subplot(2,2,1) # 创建一个两行两列的图表,并选择第一块 f1.plot(months,sales, color='blue', alpha=0.5, marker='o', linewidth=2) f2 = plt.subplot(2,2,2) f2.bar(months,sales, color='blue', alpha=0.5, width=0.5) f3 = plt.subplot(2,2,3) f3.scatter(months,sales, color='blue', alpha=0.5, marker='o') f4 = plt.subplot(2,2,4) f4.barh(months,sales, color='blue', alpha=0.5, height=0.5) # 自动优化图形 plt.tight_layout() # 显示图表 plt.show()

3. 分析案例:温度分析
-
气温趋势折线图
# 1.导入库、设置字体 import matplotlib.pyplot as plt import pandas as pd from matplotlib import rcParams rcParams['font.sans-serif'] = ['Microsoft YaHei'] # 2.导入数据 df = pd.read_csv('weather.csv') # 3.绘制气温的趋势变化图 # 先处理日期'date'格式 df['date']=pd.to_datetime(df['date']) # 取2015年全年数据 df = df[df['date'].dt.year==2015] # 取平均气温 df['temp_mean']=(df['temp_max']+df['temp_min'])/2 # 设置画布大小 plt.figure(figsize=(16,9)) # 绘制折线图 plt.plot(df['date'],df['temp_max'],label='最高气温') plt.plot(df['date'],df['temp_min'],label='最低气温') plt.plot(df['date'],df['temp_mean'],label='平均气温') # 添加标题 plt.title('2015年气温趋势变化图',color = 'blue', fontsize = 20) # 标题颜色,标题大小 # 添加标签 plt.xlabel('日期',fontsize=15) # X轴标签 plt.ylabel('气温',fontsize=15) # Y轴标签 # 添加图例(两种方法) plt.legend() # 设置刻度字体大小 plt.xticks(rotation=0,fontsize=15)# x轴旋转角度,刻度字体大小 plt.yticks(rotation=0,fontsize=15)# y轴旋转角度,刻度字体大小 # 自动优化图表 plt.tight_layout() # 显示图表 plt.show()
更多推荐
所有评论(0)