当前位置: 首页 > article >正文

Python NumPy(5):广播、迭代

1 NumPy 广播(Broadcast)

        广播(Broadcast)是 numpy 对不同形状(shape)的数组进行数值计算的方式, 对数组的算术运算通常在相应的元素上进行。如果两个数组 a 和 b 形状相同,即满足 a.shape == b.shape,那么 a*b 的结果就是 a 与 b 数组对应位相乘。这要求维数相同,且各维度的长度相同。

import numpy as np

a = np.array([1, 2, 3, 4])
b = np.array([10, 20, 30, 40])
c = a * b
print(c)

# 当运算中的 2 个数组的形状不同时,numpy 将自动触发广播机制。如:
a = np.array([[0, 0, 0],
              [10, 10, 10],
              [20, 20, 20],
              [30, 30, 30]])
b = np.array([0, 1, 2])
print(a + b)

        下面的图片展示了数组 b 如何通过广播来与数组 a 兼容。

        4x3 的二维数组与长为 3 的一维数组相加,等效于把数组 b 在二维上重复 4 次再运算:

import numpy as np

a = np.array([[0, 0, 0],
              [10, 10, 10],
              [20, 20, 20],
              [30, 30, 30]])
b = np.array([1, 2, 3])
bb = np.tile(b, (4, 1))  # 重复 b 的各个维度
print(a + bb)

        广播的规则:

  • 让所有输入数组都向其中形状最长的数组看齐,形状中不足的部分都通过在前面加 1 补齐。
  • 输出数组的形状是输入数组形状的各个维度上的最大值。
  • 如果输入数组的某个维度和输出数组的对应维度的长度相同或者其长度为 1 时,这个数组能够用来计算,否则出错。
  • 当输入数组的某个维度的长度为 1 时,沿着此维度运算时都用此维度上的第一组值。

        对两个数组,分别比较他们的每一个维度(若其中一个数组没有当前维度则忽略),满足:

  • 数组拥有相同形状。
  • 当前维度的值相等。
  • 当前维度的值有一个是 1。

2 NumPy 迭代数组

        NumPy 迭代器对象 numpy.nditer 提供了一种灵活访问一个或者多个数组元素的方式。迭代器最基本的任务的可以完成对数组元素的访问。使用 arange() 函数创建一个 2X3 数组,并使用 nditer 对它进行迭代。

import numpy as np

a = np.arange(6).reshape(2, 3)
print('原始数组是:')
print(a)
print('\n')
print('迭代输出元素:')
for x in np.nditer(a):
    print(x, end=", ")
print('\n')

        以上实例不是使用标准 C 或者 Fortran 顺序,选择的顺序是和数组内存布局一致的,这样做是为了提升访问的效率,默认是行序优先(row-major order,或者说是 C-order)。这反映了默认情况下只需访问每个元素,而无需考虑其特定顺序。我们可以通过迭代上述数组的转置来看到这一点,并与以 C 顺序访问数组转置的 copy 方式做对比,如下实例:

import numpy as np

a = np.arange(6).reshape(2, 3)
for x in np.nditer(a.T):
    print(x, end=", ")
print('\n')

for x in np.nditer(a.T.copy(order='C')):
    print(x, end=", ")
print('\n')

        从上述例子可以看出,a 和 a.T 的遍历顺序是一样的,也就是他们在内存中的存储顺序也是一样的,但是 a.T.copy(order = 'C') 的遍历结果是不同的,那是因为它和前两种的存储方式是不一样的,默认是按行访问。

2.1 控制遍历顺序

  • for x in np.nditer(a, order='F'):Fortran order,即是列序优先;
  • for x in np.nditer(a.T, order='C'):C order,即是行序优先;

        可以通过显式设置,来强制 nditer 对象使用某种顺序:

import numpy as np

a = np.arange(0, 60, 5)
a = a.reshape(3, 4)
print('原始数组是:')
print(a)
print('\n')
print('原始数组的转置是:')
b = a.T
print(b)
print('\n')
print('以 C 风格顺序排序:')
c = b.copy(order='C')
print(c)
for x in np.nditer(c):
    print(x, end=", ")
print('\n')
print('以 F 风格顺序排序:')
c = b.copy(order='F')
print(c)
for x in np.nditer(c):
    print(x, end=", ")

2.2 修改数组中元素的值

        nditer 对象有另一个可选参数 op_flags。 默认情况下,nditer 将视待迭代遍历的数组为只读对象(read-only),为了在遍历数组的同时,实现对数组元素值的修改,必须指定 readwrite 或者 writeonly 的模式。

import numpy as np

a = np.arange(0, 60, 5)
a = a.reshape(3, 4)
print('原始数组是:')
print(a)
print('\n')
for x in np.nditer(a, op_flags=['readwrite']):
    x[...] = 2 * x
print('修改后的数组是:')
print(a)

2.3 使用外部循环

        nditer 类的构造器拥有 flags 参数,它可以接受下列值:

参数描述
c_index可以跟踪 C 顺序的索引
f_index可以跟踪 Fortran 顺序的索引
multi_index每次迭代可以跟踪一种索引类型
external_loop给出的值是具有多个值的一维数组,而不是零维数组

        在下面的实例中,迭代器遍历对应于每列,并组合为一维数组。

import numpy as np

a = np.arange(0, 60, 5)
a = a.reshape(3, 4)
print('原始数组是:')
print(a)
print('\n')
print('修改后的数组是:')
for x in np.nditer(a, flags=['external_loop'], order='F'):
    print(x, end=", ")

2.4 广播迭代

        如果两个数组是可广播的,nditer 组合对象能够同时迭代它们。 假设数组 a 的维度为 3X4,数组 b 的维度为 1X4 ,则使用以下迭代器(数组 b 被广播到 a 的大小)。

import numpy as np

a = np.arange(0, 60, 5)
a = a.reshape(3, 4)
print('第一个数组为:')
print(a)
print('\n')
print('第二个数组为:')
b = np.array([1, 2, 3, 4], dtype=int)
print(b)
print('\n')
print('修改后的数组为:')
for x, y in np.nditer([a, b]):
    print("%d:%d" % (x, y), end=", ")


http://www.kler.cn/a/523270.html

相关文章:

  • 小程序-视图与逻辑
  • 【Elasticsearch 】悬挂索引(Dangling Indices)
  • WSL 安装cuDNN
  • C语言自定义数据类型详解(二)——结构体类型(下)
  • 为AI聊天工具添加一个知识系统 之76 详细设计之17 正则表达式 之4 正则表达式模板
  • git困扰的问题
  • 单片机基础模块学习——蜂鸣器及继电器
  • 关于低代码技术架构的思考
  • centos安装mysql
  • 【Linux】Linux C判断两个IPv6地址是否有包含关系
  • Ansible自动化运维实战--软件包管理模块、服务模块、文件模块和收集模块setup(4/8)
  • 【UE】 Pawn
  • 基于SpringBoot的高校一体化服务平台的设计与实现(源码+SQL脚本+LW+部署讲解等)
  • 力扣【669. 修剪二叉搜索树】Java题解
  • 【Super Tilemap Editor使用详解】(十七):常见问题解答(FAQ)
  • 初始JavaEE篇 —— Spring Web MVC入门(上)
  • 笔记本搭配显示器
  • 【Git】使用笔记总结
  • 数据结构的学习要点
  • OpenAI-Edge-TTS:本地化 OpenAI 兼容的文本转语音 API,免费高效!
  • 【C语言练习题】数字螺旋方阵
  • 小南每日 AI 资讯 | AI将向“少样本学习”发展? | 25/01/25
  • 【Leetcode 热题 100】416. 分割等和子集
  • 在Windows下安装Ollama并体验DeepSeek r1大模型
  • LangChain概述
  • 开关电路汇总