NumPy数组广播机制

数组广播机制

  • 一. 数组与数的运算
    • 1.普通列表计算
    • 2. 数组与数计算
  • 二. 数组与数组的运算
    • 满足两个重要条件
    • 1. 结构相同的数组之间的运算
    • 2. 与行相同,只有一列的数组的运算
    • 3. 与列相同,只有一行的数组的运算
    • 4. 不同维度数组之间的运算
  • 参考资料

一. 数组与数的运算

1.普通列表计算

在python中,对一个列表所有元素加上一个数,需要使用map()函数,对列表中每个元素加上一个值。

例如,对一个列表中所有元素加上3

list_test = [-1, 2, -3, 4, -5]

res = map(lambda x: x+3, list_test)

list(res)

结果:

[2, 5, 0, 7, -2]

map()函数的用法

结构:
map(function, iterable, …)

参数:
function - 函数或匿名函数
iterable - 一个或多个序列

实例:
对于这样一个列表进行操作

list_test = [1, -2, 3, -4, 5]

(1). 普通函数

def square_num(x):
    return x**2

res = map(square_num, list_test)

list(res)

结果:

[1, 4, 9, 16, 25]

(2). 匿名函数

res = map(lambda x: x-3, list_test)

list(res)

结果:

[-2, -5, 0, -7, 2]

(3). 多个序列

# 额外提供一个列表
list_ extra = [-1, 2, -3, 4, -5]

res = map(lambda x, y: x+y, list_test, list_extra)
list(res)

结果:

[0, 0, 0, 0, 0]

2. 数组与数计算

NumPy中的数组可以直接进行操作

import numpy as np
n1 = np.array([[1,2,3],[4,5,6]])
n1

结果:

array([[1, 2, 3],
       [4, 5, 6]])

进行计算:

n1 + 9

结果:

array([[10, 11, 12],
       [13, 14, 15]])

相减、相乘、相除都是类似的操作

二. 数组与数组的运算

满足两个重要条件

1. 维度上,从右往左进行匹配;在同一维度上,要么两个数组的长度相同,要么其中一个为1

如:(3,1,8) 和 (4,1)
第一个数组的8和第二个数组的1对应,为同一维度;第一个数组的1和第二个数组的4对应,为同一维度。他们同一维度的长度不同,但其中一个都为1。

2. 两个数组都以对应相同维度最长长度为基准进行拓展对齐(广播);有些维度为0长度的,先将长度变成1,再进行拓展对齐(广播)

如:(3,1,8) 和 (4,1)
第二个数组缺少一个维度,先补成1,即:(1,4,1), 再按照相同维度上最长长度为基准进行拓展,即:第一个数组:(3, 1, 8) - > (3, 4, 8), 第二个数组:(4, 1) - > (1, 4, 1) - > (3, 4, 8)

1. 结构相同的数组之间的运算

import numpy as np
n1 = np.array([[ 1,2, 3],[4, 5,6]])
n2 = np.array([[-1,2,-3],[4,-5,6]])
n1 + n2

结果:

array([[ 0,  4,  0],
       [ 8,  0, 12]])

2. 与行相同,只有一列的数组的运算

n1 = np.array([[ 1,2, 3],[4, 5,6]]) 
n2 = np.array([[-1],[4]])

n1 + n2

n1:

array([[1, 2, 3],
       [4, 5, 6]])

n2:

array([[-1],
       [ 4]])

结果:

array([[ 0,  1,  2],
       [ 8,  9, 10]])

可以看出: 尽管n2第一行只有-1,但-1与n1的第一行[1,2,3]都参与了运算,实现了列的广播传递

3. 与列相同,只有一行的数组的运算

n1 = np.array([[ 1,2, 3],[4, 5,6]]) 
n2 = np.array([[-1,2,-3]])

n1 + n2

n1:

array([[1, 2, 3],
       [4, 5, 6]])

n2:

array([[-1,  2, -3]])

结果:

array([[0, 4, 0],
       [3, 7, 3]])

可以看出:尽管n2只有一列[-1, 2, -3],但这一列与n1每一行都参与运算,实现了行的广播传递

4. 不同维度数组之间的运算

import numpy as np
n1 = np.random.randint(0,12,size=(3,1,8))
n2 = np.random.randint(0,8, size=(4,1))

display(n1, n2)

n1和n2:

# n1
array([[[ 0,  7,  5, 10,  7,  3,  5,  5]],

       [[ 2,  8,  5, 10,  6,  2,  1,  2]],

       [[10, 10,  6,  1,  3,  0,  5,  7]]])
 # n2
array([[4],
       [5],
       [3],
       [2]])

n1 + n2:

array([[[ 4, 11,  9, 14, 11,  7,  9,  9],
        [ 5, 12, 10, 15, 12,  8, 10, 10],
        [ 3, 10,  8, 13, 10,  6,  8,  8],
        [ 2,  9,  7, 12,  9,  5,  7,  7]],

       [[ 6, 12,  9, 14, 10,  6,  5,  6],
        [ 7, 13, 10, 15, 11,  7,  6,  7],
        [ 5, 11,  8, 13,  9,  5,  4,  5],
        [ 4, 10,  7, 12,  8,  4,  3,  4]],

       [[14, 14, 10,  5,  7,  4,  9, 11],
        [15, 15, 11,  6,  8,  5, 10, 12],
        [13, 13,  9,  4,  6,  3,  8, 10],
        [12, 12,  8,  3,  5,  2,  7,  9]]])

分析按照前面的两个条件为标准

n1由shape为(3,1,8):

array([[[ 0,  7,  5, 10,  7,  3,  5,  5]],

       [[ 2,  8,  5, 10,  6,  2,  1,  2]],

       [[10, 10,  6,  1,  3,  0,  5,  7]]])

变成shape为(3,4,8):第二个数组(4,1)的4长度大,按4标准补齐

array([[[ 0,  7,  5, 10,  7,  3,  5,  5]
		[ 0,  7,  5, 10,  7,  3,  5,  5]
		[ 0,  7,  5, 10,  7,  3,  5,  5]
		[ 0,  7,  5, 10,  7,  3,  5,  5]],

       [[ 2,  8,  5, 10,  6,  2,  1,  2]
        [ 2,  8,  5, 10,  6,  2,  1,  2]
        [ 2,  8,  5, 10,  6,  2,  1,  2]
        [ 2,  8,  5, 10,  6,  2,  1,  2]],

       [[10, 10,  6,  1,  3,  0,  5,  7]
        [10, 10,  6,  1,  3,  0,  5,  7]
        [10, 10,  6,  1,  3,  0,  5,  7]
        [10, 10,  6,  1,  3,  0,  5,  7]]])

n2由shape为(4,1):

array([[4],
       [5],
       [3],
       [2]])

变成shape为(1,4,1): 缺一个维度补1

array([[[4],
        [5],
        [3],
        [2]]])

再变成shape为(3,4,8): 按第一个数组的相同维度最长长度进行拓展

array([[[4, 4, 4, 4, 4, 4, 4, 4],
        [5, 5, 5, 5, 5, 5, 5, 5],
        [3, 3, 3, 3, 3, 3, 3, 3],
        [2, 2, 2, 2, 2, 2, 2, 2]]
        
       [[4, 4, 4, 4, 4, 4, 4, 4],
        [5, 5, 5, 5, 5, 5, 5, 5],
        [3, 3, 3, 3, 3, 3, 3, 3],
        [2, 2, 2, 2, 2, 2, 2, 2]]
        
       [[4, 4, 4, 4, 4, 4, 4, 4],
        [5, 5, 5, 5, 5, 5, 5, 5],
        [3, 3, 3, 3, 3, 3, 3, 3],
        [2, 2, 2, 2, 2, 2, 2, 2]]])

n1 + n2进行运算:
NumPy数组广播机制_第1张图片NumPy数组广播机制_第2张图片

对应相加,结果为:
NumPy数组广播机制_第3张图片
补充一点:

其实,在数组与数的运算中,也满足上述的2个规律:

n1 = np.array([[1,2,3], [4,5,6]])

b = 1

n1 + b

将b转化成一维数组,shape为(1,):

array([1])

进行维度扩充,shape为(1,1):

array([[1]])

按相同维度最大长度进行拓展,变成shape为(2,3)

array([[1,1,1],
	   [1,1,1]])

最后:

# n1                          # b
array([[1,2,3],               array([[1,1,1],
       [4,5,6]])                     [1,1,1]])

结果:

array([[2,3,4],
	   [5,6,7]])

参考资料

[开发技巧]·Numpy广播机制的深入理解与应用

你可能感兴趣的:(Data,Analysis,NumPy,数组广播,python,数据分析)