Python学习笔记·第19天:NumPy进阶——布尔筛选、形状变换与分段函数

一、数组对函数运算的支持

NumPy支持对整个数组直接进行数学函数运算,无需写循环。

python 复制代码
import numpy as np

x = np.arange(0, 100, 10, dtype=np.floating)

print(np.sin(x))      # 数组中所有元素求正弦值
print(np.cos(x))      # 所有元素求余弦值
print(np.round(np.cos(x)))  # 四舍五入
print(np.ceil(x/2))   # 向上取整

核心理解np.sin(x) 不是对单个值求正弦,而是对数组里每一个元素同时求正弦。这就是NumPy的"向量化运算"。

二、改变数组形状

改变数组的形状有三种方法,区别在于是否修改原数组。

python 复制代码
x = np.arange(1, 11, 1)  # [1, 2, 3, ..., 10]

# 方法1:直接修改shape属性(原地修改)
x.shape = 2, 5            # 改成2行5列
x.shape = 5, -1           # 改成5行,-1表示自动计算列数(10/5=2列)

# 方法2:reshape()方法(返回新数组,原数组不变)
x = x.reshape(2, 5)       # 返回新数组
# 注意:reshape()不能改变元素总数,10个元素只能改成(2,5)或(5,2)等

# 方法3:resize()方法(可改变元素总数,多出的填0)
x.resize((1, 10))         # 原地修改,改成1行10列,少的填0
np.resize(x, (1, 3))      # numpy的resize()返回新数组,原数组不变

三种方法对比

方法 是否修改原数组 能否改变元素总数
x.shape = ... 原地修改 不能
x.reshape(...) 返回新数组 不能
x.resize(...) 原地修改 可以(多出填0)
np.resize(x, ...) 返回新数组 可以

三、数组的布尔运算

布尔运算是NumPy最强大的功能之一,用于条件筛选和判断。

python 复制代码
x = np.random.rand(10)    # 创建包含10个随机数的数组

# 1. 数组与常量比较(返回布尔数组)
x > 0.5                   # 每个元素判断是否大于0.5,返回True/False数组
x[x > 0.5]                # 获取数组中大于0.5的元素(布尔索引)

# 2. 组合条件(使用 & 和 |,不是 and 和 or)
sum((x > 0.4) & (x < 0.6)) # 大于0.4且小于0.6的元素个数
# True当作1,False当作0,sum求和就是计数

# 3. 整体判断
np.all(x < 1)             # 数组中所有元素都小于1?全True才返回True
np.any(x > 0.8)           # 数组中存在大于0.8的元素?有一个True就返回True

# 4. 两个数组之间比较(逐个对应位置比较)
a = np.array([1, 2, 3])
b = np.array([3, 2, 1])
a > b                     # [False, False, True]
a[a > b]                  # 取出a中大于b对应位置元素的值 → [3]
a[a == b]                 # 取出a中等于b对应位置元素的值 → [2]

# 5. 多条件筛选
x = np.arange(1, 10)
x[(x % 2 == 0) & (x > 5)]    # 大于5的偶数(布尔与)
x[(x % 2 == 0) | (x > 5)]    # 大于5或者偶数(布尔或)

关键注意

  • 组合条件用 &|(位运算符),不是 andor(逻辑运算符)
  • 每个条件必须用括号括起来,如 (x > 4) & (x < 6)

四、分段函数

用于根据条件对数组元素进行分类处理。

python 复制代码
x = np.random.randint(0, 10, size=(1, 10))

# 1. np.where():二分类
np.where(x < 5, 0, 1)    # 小于5的元素变为0,大于等于5的元素变为1
# 类似于三目运算:满足条件取值A,不满足取值B

# 2. np.piecewise():多分类
np.piecewise(x, [x < 4, x > 7], [lambda x: x**2, lambda x: x*3])
# 小于4的元素 → 求平方
# 大于7的元素 → 乘以3
# 其他所有未覆盖的元素 → 变为0

np.piecewise(x, [x < 3, (3 < x) & (x < 5), x > 7], [-1, 1, lambda x: x*4])
# 小于3 → -1
# 大于3且小于5 → 1
# 大于7 → 乘以4
# 其他 → 0

piecewise()参数解析

  • 第1个参数:要操作的数组
  • 第2个参数:条件列表 [条件1, 条件2, ...]
  • 第3个参数:处理列表 [处理1, 处理2, ...],可以是具体值或lambda函数
  • 条件没有覆盖到的元素 → 自动变为0

今日核心总结

  1. 函数运算np.sin(x) 对整个数组逐元素运算,无需写循环。

  2. 形状变换三方法

    • shape 属性原地修改
    • reshape() 返回新数组(不改变元素总数)
    • resize() 可改变元素总数(多出填0)
  3. 布尔运算核心

    • x[x > 0.5] 是NumPy中筛选数据最常用的方式
    • 组合条件用 &|,每个条件必须加括号
    • np.all() 全真才真,np.any() 一真则真
  4. 分段函数

    • np.where() 适合二分类
    • np.piecewise() 适合多分类,未覆盖的条件自动归零

说明一下:前几天没有更新是因为端午节放假,家里还有很多事情需要忙,一忙完就没时间学了,而且前几天一直沉迷于Ai写代码了。

注:已经使用DeepSeek进行整理精简核心内容,些许不理解的配合个人笔记进行理解。