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
    1. 什么是同质性? ✅ NumPy 数组必须满足:整个数组里所有元素,只能是同一种数据类型 ❌ 不能像 Python 列表一样:同时存 int、str、float、bool 随意混搭

    2. 类型强制转换规则 当你放入多种不同类型数据时,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 个特点(必考)

    1. 形状完全相同(几行几列一模一样)

    2. 数据类型完全相同(float 还是 float,int 还是 int)

    3. 只有数值变了(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()

数据特点:服从标准正态分布的随机浮点数 什么是标准正态分布?

  1. 平均值(均值)= 0

  2. 标准差 = 1

  3. 分布规律:

  • 大部分数字集中在 0 附近

  • 离 0 越远,数字出现的概率越小

  • 可正、可负

  1. 取值范围:理论上无上下限,但绝大多数值在 [-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,不包含 b randint(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()
  1. np.random.seed(42) 作用:固定随机种子

    • 只要种子数字一样,每次生成的随机数都完全相同

    • 42 只是一个随便选的数字(可以换成 0、1、100 都行)

    • 目的:让随机结果可复现

  2. 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 一维数组的索引与切片
  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
  2. 全切片:获取所有元素

    • [:]省略起始索引结束索引,代表选取数组中所有元素,等价于直接打印arr

    • 代码

    print(f"arr[:]: {arr[:]}")
    • 结果

    arr[:]: [40 71  3 63 98 83 34  1 38  5 35  9 89  3 62]
  3. 范围切片:左闭右开 [起始索引, 结束索引)

    • 语法: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]
  4. slice对象切片:指定 (起始,结束,步长)

    1. slice(start, stop, step):Python 内置切片对象,等价于简写 [start:stop:step]

    2. 参数含义:

    • 2起始索引;

    • 15结束索引(不包含);

    • 3步长(每隔 3 个元素取 1 个);

    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]
  5. 布尔索引:根据条件筛选元素

    1. arr>50 会生成一个布尔数组(元素为True/False);

    2. 用布尔数组作为索引,只保留值为 True 的元素

    • 代码

    print(f"arr[arr>50]: {arr[arr>50]}")
    • 结果

    arr[arr>50]: [71 63 98 83 89 62]
  6. 多条件布尔索引:& 表示且,| 表示或

    1. 逻辑:用 &,不能用and

    2. 逻辑:用 |,不能用or

    3. 每个条件必须加括号()

    4. 作用:筛选出 大于 50 且 小于 80 的元素。

    • 代码

    print(f"arr[(arr>50) & (arr<80)]: {arr[(arr>50) & (arr<80)]}")
    • 结果

    arr[(arr>50) & (arr<80)]: [71 63 62]
  7. 布尔索引修改元素:满足条件的元素直接赋值为0

    1. 布尔索引不仅能筛选,还能直接赋值修改

    2. 作用:将数组中所有满足 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 二维数组的索引与切片
  1. 取单个元素:行索引,列索引

    1. 二维索引语法arr[行索引, 列索引]

    2. 规则:行、列索引都从 0 开始

    3. 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
  2. 取全部元素

    1. [:] = 所有行 + 所有列

    2. 等价于直接打印 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]]
  3. 取整行:第2行所有列

    1. 语法:arr[行号, :]

    2. : 代表所有列

    3. arr[1,:] = 第 2 行全部元素(结果是一维数组)

    • 代码

    print(f"arr[1,:]: {arr[1,:]}")
    • 结果

    arr[1,:]: [10 31 52 38 19 25 55 98]
  4. 取整列:所有行第3列

    1. 语法:arr[:, 列号]

    2. : 代表所有行

    3. arr[:,2] = 第 3 列全部元素(结果是一维数组)

    • 代码

    print(f"arr[:,2]: {arr[:,2]}")
    • 结果

    arr[:,2]: [98 52 75 47]
  5. 区域切片:第2行,第3列~第5列

    1. 语法:arr[行, 列起始:列结束]

    2. 规则:左闭右开

    3. 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]
  6. 全局布尔索引:所有>50的元素(结果自动展平为一维)

    1. 整个二维数组做条件筛选;

    2. 自动把满足条件的元素全部抽出来,展平成一维数组

    3. 用途:快速查找整个矩阵中符合条件的所有值。

    • 代码

    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]
  7. 行内布尔索引:(先取行,再筛选) ,第2行中>50的元素

    1. arr[1,:] → 先拿到第 2 行(一维)

    2. arr[1,:]>50 → 生成布尔条件

    3. 再用布尔索引筛选 → 得到第 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 一维数组的数组间运算
  1. NumPy数组直接进行 加、减、乘、除 运算

    1. 规则对应位置元素直接运算,无需写循环!

    2. 运算逻辑:

      • 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 ]
  2. Python原生列表的运算

    1. 列表 + 不是数学加法,是拼接:把两个列表首尾连在一起。

    2. 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 多维数组的数组间运算
  1. 所有运算都是:相同行、相同列的元素,一一对应计算

  2. 两个多维数组的 shape(形状)必须完全一致

  1. 对应元素相加

    第 1 行:1+7=82+8=103+9=12

    第 2 行:4+4=85+5=106+6=12

    第 3 行:7+1=88+2=109+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]]
  2. 对应元素相减

    • 代码

    print(f"a-b: \n{a-b}")
    • 结果

    a-b: 
    [[-6 -6 -6]
     [ 0  0  0]
     [ 6  6  6]]
  3. 对应元素相乘(点乘,不是矩阵乘法!)

    1. 重点:这是元素级乘法(点乘),不是线性代数里的矩阵乘法!

    2. 规则: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]]
  4. 对应元素相除,np.round保留2位小数

    1. a/b:对应元素相除,结果是浮点数;

    2. 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. 每个元素 +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. 每个元素 ×2

    a * 2

    • 等价于:[[1×2, 2×2, 3×2]]

    • 结果:[[2 4 6]]

    • 代码

    print(f"a*2: {a*2}") 
    • 结果

    a*2: [[2 4 6]]
  3. 每个元素 平方

    a ** 2

    • 等价于:[[1², 2², 3²]]

    • 结果:[[1 4 9]]

    • 代码

    print(f"a**2: {a**2}") 
    • 结果

    a**2: [[1 4 9]]
  4. 每个元素 ÷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 广播机制
  1. 广播机制允许 NumPy 在算术运算期间处理不同形状的数组。它会自动"扩展"较小的数组以匹配较大数组的形状,从而进行元素级运算。

  2. 两个数组要能广播,必须满足以下条件之一:

    • 维度数相同,且每个维度的大小相同或其中一个为 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]]
  1. 数组的形状

    a = [1, 2, 3]        → shape (1, 3)  1行3列
    b = [[4],
         [5],
         [6]]            → shape (3, 1)  3行1列
  2. 广播会把两个数组自动扩展成相同形状(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 矩阵运算
  1. 推荐写法(简洁): a @ b

  2. 函数写法: np.matmul(a, b)

  3. 点积函数(二维等价): np.dot(a, b)

  4. 二维时:np.dot = @ = np.matmul

  5. @ 不支持一维运算,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(条件)任意一个满足 → True np.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. 显式索引:locat

① 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. 隐式索引:ilociat

① 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

    image-20260502132616596

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

    image-20260502132845058

2. 描述统计:describe()

自动计算: 个数、均值、标准差、最小值、25%/50%/75% 分位数、最大值

  • 代码

     # 查看所有的描述性信息
     s.describe()
  • 结果

    image-20260502133056363

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')

    image-20260502133359212

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
    ```
  • 结果

    image-20260502133510912

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
  • 结果

    ①按值排序:

    image-20260502133758566

    ②s.unique()

    • array([77., 32., nan, 54., 12.])

    ③s.drop_duplicates()

    image-20260502133956463

6. 相邻差值:diff()

后一个数 − 前一个数 → 取绝对值

  • 代码

    # 计算相邻元素之间的差值(一阶差分)
    s.diff().abs()
  • 结果

    image-20260502134240107

7. 生成时间序列:pd.date_range()
  1. 基本语法:

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

  1. 常用频率别名(freq)

      1. 日期频率

        频率代码 说明 示例输出 适用场景
        'D' 日历日 2026-01-01, 2026-01-02, ... 日度数据
        'B' 工作日(周一至周五) 2026-01-01(Thu), 2026-01-02(Fri), ... 股票交易、业务数据
        'C' 自定义工作日 需自定义 特殊工作日历
      1. 周频率

        频率代码 说明 示例输出 适用场景
        'W''W-SUN' 每周日 2026-01-04, 2026-01-11, ... 周报
        'W-MON' 每周一 2026-01-05, 2026-01-12, ... 周报
        'W-TUE' ~ 'W-SAT' 每周二~六 类似 周报
      1. 月频率

        频率代码 说明 示例输出 适用场景
        '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), ... 业务结算
      1. 季度频率

        频率代码 说明 示例输出 适用场景
        '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, ... 财年报表
      1. 年频率

        频率代码 说明 示例输出 适用场景
        '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, ... 财年报表
      1. 时间频率

        频率代码 说明 示例输出 适用场景
        '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' 微秒 - 超高频数据
      1. 复合频率

        频率代码 说明 示例 输出间隔
        '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')
  1. 普通抽取

  • 代码

    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
  1. 按比例抽样 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
  1. 有放回抽样 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
  1. 固定随机结果 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
  1. 重置索引 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
  1. 带权重抽样 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)
  • 结果

    image-20260502200707125

(二) 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
  • 结果

    image-20260502205705307

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

    image-20260502205941819

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=["姓名","年龄","性别","班级","成绩"]
    )
    1. 按行标签索引

    • 代码

    # 按行标签索引
    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
    1. 按列标签索引

    • 代码

    # 按列标签索引
    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
    1. 单个元素索引

    • 代码

    # 单个元素索引
    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

    image-20260502213026434

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'}]}

    image-20260508222618085

  • 读取 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.nanNumPy 缺失值(数值型)

  • NonePython 原生空值(对象型)

  • pd.NAPandas 统一缺失值(推荐)

  • 代码

    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:

    image-20260510125100718

    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

    image-20260510130519860

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%,确保所有数据都能被归类
  • 结果

    原始数据:

    image-20260510172423457

    自动等分2个区间:

    image-20260510172540172

用法 2:统计每个区间的数量

  • 代码

    pd.cut(df1['salary'],bins=2).value_counts()
  • 结果

    image-20260510172735031

用法 3:自定义区间(最常用)

  • 代码1

    pd.cut(df1['salary'],bins=[0,10000,20000,30000]).value_counts()

    image-20260510173128420

  • 代码2:添加自定义标签

    pd.cut(df1['salary'],
           bins=[0,10000,20000,30000],
           labels=['低薪组','中薪组','高薪组']).value_counts()

    image-20260510173512114

  • 代码3:将分箱结果保存为新列

    df1['收入范围'] = pd.cut(df1['salary'],
           bins=[0,10000,20000,30000],
           labels=['低薪组','中薪组','高薪组'])
    df1

    image-20260510173703074

2. pd.qcut() 等频分箱
  • 解决 pd.cut() 数据分布不均的问题

  • 适合数据偏斜严重的场景(如工资、房价)

  • 代码

    # 把工资分成 3 个区间,每个区间人数大致相等
    pd.qcut(df1['salary'],3).value_counts()
  • 结果

    image-20260510173849477

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']
    })

    image-20260511122232716


三、数据可视化

(一)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()

更多推荐