numpy

Numpy

一、【了解】Numpy优势

Numpy介绍

Numpy(Numerical Python)是一个开源的Python科学计算库,用于快速处理任意维度的数组

Numpy支持常见的数组和矩阵操作。对于同样的数值计算任务,使用Numpy比直接使用Python要简洁的多。

Numpy使用ndarray对象来处理多维数组,该对象是一个快速而灵活的大数据容器。

ndarray:n dimension array

ndarray介绍

NumPy provides an N-dimensional array type, the ndarray, 
which describes a collection of “items” of the same type.

NumPy提供了一个N维数组类型ndarray,它描述了相同类型的“items”的集合。

image-20260525165020850

用ndarray进行存储:

import numpy as np

# 创建ndarray
score = np.array(
[[80, 89, 86, 67, 79],
[78, 97, 89, 67, 81],
[90, 94, 78, 67, 74],
[91, 91, 90, 67, 69],
[76, 87, 75, 67, 86],
[70, 79, 84, 67, 84],
[94, 92, 93, 67, 64],
[86, 85, 83, 67, 80]])

score

返回结果:

array([[80, 89, 86, 67, 79],
       [78, 97, 89, 67, 81],
       [90, 94, 78, 67, 74],
       [91, 91, 90, 67, 69],
       [76, 87, 75, 67, 86],
       [70, 79, 84, 67, 84],
       [94, 92, 93, 67, 64],
       [86, 85, 83, 67, 80]])

提问:

使用Python列表可以存储一维数组,通过列表的嵌套可以实现多维数组,那么为什么还需要使用Numpy的ndarray呢?

ndarray与Python原生list运算效率对比

在这里我们通过一段代码运行来体会到ndarray的好处

import random
import time
import numpy as np

a = []
for i in range(100000000):
    a.append(random.random())

start = time.time()
sum(a)
print("python运行耗时:",time.time()-start)

print("-"*50)

b = np.array(a)

start = time.time()
np.sum(b)
print("numpy运行耗时:",time.time()-start)

其中第一个时间显示的是使用原生Python计算时间,第二个内容是使用numpy计算时间:

python运行耗时: 0.7574722766876221
--------------------------------------------------
numpy运行耗时: 0.11530804634094238

从中我们看到ndarray的计算速度要快很多,节约了时间。

机器学习的最大特点就是大量的数据运算,那么如果没有一个快速的解决方案,那可能现在python也在机器学习领域达不到好的效果。

计算量大

Numpy专门针对ndarray的操作和运算进行了设计,所以数组的存储效率和输入输出性能远优于Python中的嵌套列表,数组越大,Numpy的优势就越明显。

思考:

ndarray为什么可以这么快?

ndarray的优势

内存块风格

ndarray到底跟原生python列表有什么不同呢,请看一张图:

image-20260525165059671

从图中我们可以看出ndarray在存储数据的时候,数据与数据的地址都是连续的,这样就给使得批量操作数组元素时速度更快。

这是因为ndarray中的所有元素的类型都是相同的,而Python列表中的元素类型是任意的,所以ndarray在存储元素时内存可以连续,而python原生list就只能通过寻址方式找到下一个元素,这虽然也导致了在通用性能方面Numpy的ndarray不及Python原生list,但在科学计算中,Numpy的ndarray就可以省掉很多循环语句,代码使用方面比Python原生list简单的多。

ndarray支持并行化运算(向量化运算)

numpy内置了并行运算功能,当系统有多个核心时,做某种计算时,numpy会自动做并行计算

效率远高于纯Python代码

Numpy底层使用C语言编写,内部解除了GIL(全局解释器锁),其对数组的操作速度不受Python解释器的限制,所以,其效率远高于纯Python代码。

二、ndarray数据结构

掌握内容

属性
    shape
    dtype

ndarray的属性

数组属性反映了数组本身固有的信息。

属性名字属性解释
ndarray.shape数组维度的元组
ndarray.ndim数组维数
ndarray.size数组中的元素数量(个数)
ndarray.itemsize一个数组元素的长度(字节)
ndarray.dtype数组元素的类型

ndarray的形状

首先创建一些数组。

arr1 = np.array([11, 22, 33, 44])
print("arr1的维度个数:",arr1.ndim)
print("arr1的形状:",arr1.shape)    # 4个元素
print("arr1的元素数据类型:",arr1.dtype)


arr2 = np.array([
    [1,2,3],
    [4,5,6]
])
print("arr2的维度个数:",arr2.ndim) # 2
print("arr2的形状:",arr2.shape) # 2行3列
print("arr2的元素数据类型:",arr2.dtype)


arr3 = np.array([
    [
        [1,2,3],
        [4,5,6]
    ],
    [
        [1,2,3],
        [4,5,6]
    ]
])
print("arr3的元素个数:",arr3.size)   # 12个元素
print("arr3的维度个数:",arr3.ndim) # 3
print("arr3的形状:",arr3.shape) # 2,2,3
print("arr3的元素数据类型:",arr3.dtype)

如何理解数组的形状?

二维数组:

image-20260525165119841

三维数组:

image-20260525165131498

ndarray的类型

名称描述简写
np.bool用一个字节存储的布尔类型(True或False)‘b’
np.int8tinyint一个字节大小,-128 至 127‘i’
np.int16smallint整数,-32768 至 32767‘i2’
np.int32int整数,-2^31​ 至 2^32 -1‘i4’
np.int64bigint整数,-2^63 至 2^63 - 1‘i8’
np.uint8tinyint unsigned==无符号==整数,0 至 255‘u’
np.uint16smallint unsigned无符号整数,0 至 65535‘u2’
np.uint32无符号整数,0 至 2^32 - 1‘u4’
np.uint64无符号整数,0 至 2^64 - 1‘u8’
np.float16半精度浮点数:16位,正负号1位,指数5位,精度10位‘f2’
np.float32float单精度浮点数:32位,正负号1位,指数8位,精度23位‘f4’
np.float64double双精度浮点数:64位,正负号1位,指数11位,精度52位‘f8’
np.complex64复数,分别用两个32位浮点数表示实部和虚部‘c8’
np.complex128复数,分别用两个64位浮点数表示实部和虚部‘c16’
np.object_python对象‘O’
np.string_字符串‘S’
np.unicode_unicode类型(字符串)‘U’

常用的几个:

无符号:只有正数,没有负数,也就是>=0

**np.int32**:32位整数,是最常用的整数类型,适用于大多数整数运算。

**np.float64**:64位浮点数,是默认的浮点数类型,广泛用于科学计算。

**np.bool_**:布尔类型,用于表示True或False,常用于条件判断和逻辑操作。

**np.string_/np.unicode_**:定长字符串类型,常用于二进制数据 或 多语言文本数据

**np.object_**:用于存储任意Python对象,特别是在处理混合类型数据或需要灵活性的时候。

np.string_只支持ASCII编码,不支持Unicode,而np.unicode_支持Unicode字符。

np.string_更适合处理旧有的二进制数据,而np.unicode_更适合处理现代文本数据。

创建数组的时候指定类型

# 小数转成整数,直接舍弃所有的小数内容,只保留整数部分
arr5 = np.array([[1.999, 2.123, 3.456],[4.5, 5.6, 6.7]], dtype=np.int32)
arr5,arr5.dtype

# S15:S是string的首字母;15表示的是最长字符串的长度
arr6 = np.array(['python', 'tensorflow', 'scikit-learnabc', 'numpy'], dtype=np.string_)
arr6,arr6.dtype

arr7 = np.array([[1, 2, 3],[4, 5, 6]], dtype=np.double) # double就是float64
arr7,arr7.dtype
  • 注意:若不指定,整数默认int64,小数默认float64

三、基本操作

掌握内容

生成数组
    ones
    zeros
    array
    arange
    np.random.randint
    
索引切片
    二维数组[行索引开始:行索引结束:步长, 列索引开始:列索引结束:步长],注意是左闭右开的区间
    
形状修改
    reshape
    T
    
去重
    unique

生成数组的方法

生成0和1的数组

  • **np.ones(shape, dtype)**:创建形状指定的,并且元素值都为1的数组
  • np.ones_like(a, dtype) :用于创建一个与数组 a 形状相同且所有元素都为1的数组的函数。
  • **np.zeros(shape, dtype)**:创建形状指定的,并且元素值都为0的数组
  • np.zeros_like(a, dtype) : :用于创建一个与数组 a 形状相同且所有元素都为0的数组的函数。
ones = np.ones([4,8])
ones

返回结果:

array([[1., 1., 1., 1., 1., 1., 1., 1.],
       [1., 1., 1., 1., 1., 1., 1., 1.],
       [1., 1., 1., 1., 1., 1., 1., 1.],
       [1., 1., 1., 1., 1., 1., 1., 1.]])
np.zeros_like(ones)

返回结果:

array([[0., 0., 0., 0., 0., 0., 0., 0.],
       [0., 0., 0., 0., 0., 0., 0., 0.],
       [0., 0., 0., 0., 0., 0., 0., 0.],
       [0., 0., 0., 0., 0., 0., 0., 0.]])

从现有数组生成

  • **np.array(object, dtype)**:新建一个,相当于深拷贝
  • **np.asarray(a, dtype)**:没有新建,引用指向同一片内存区域,相当于浅拷贝
import numpy as np

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

# 从现有的数组当中创建
a1 = np.array(a)
id(a1)

# 相当于浅拷贝,并没有真正的创建一个新的
a2 = np.asarray(a)
id(a2)

# 修改值
a[1,1] = 99

print(f"a--->{a}")
print(f"a1--->{a1}")
print(f"a2--->{a2}")

生成固定范围的数组

类似于之前讲过的range()

np.linspace (start, stop, num, endpoint)

  • 创建等差数组 — ==指定数量==
  • 参数:
    • start:序列的起始值
    • stop:序列的终止值
    • num:要生成的等间隔样例数量,默认为50
    • endpoint:序列中是否包含stop值,默认为True
"""
    参数解释:
        start:开始值
        stop:结束值
        endpoint:stop是否包含在内
        num:等差数组中元素的个数
"""
arr9 = np.linspace(start=1,stop=10,num=10,endpoint=True) 
arr9    # 产生的是 10行1列 的 列向量(既有大小,也有方向)

np.arange(start,stop, step, dtype)

  • 创建等差数组 — ==指定步长==
  • 参数
    • step:步长,默认值为1
# np.arange:使用和参数与range函数完全一样
arr10 = np.arange(start=1,stop=6,step=2)
arr10

np.logspace(start,stop, num)

  • 创建等比数列

  • 参数:

    • num:要生成的等比数列数量,默认为50
"""
    参数解释: 
        start:开始值
        stop:结束值
        endpoint:stop是否包含在内
        num:等差数组中元素的个数
        base:幂次方的底。a**x,也就是这里的a的值
"""
arr11 = np.logspace(start=0,stop=5,num=6,endpoint=True,base=10)
arr11 = np.logspace(start=0,stop=5,num=6,endpoint=True,base=2)
arr11

生成随机数组

使用模块介绍

  • np.random模块
# 设置随机数种子
np.random.seed(523)

"""
    np.random.rand():产生0-1的随机小数;结果数据是均匀分布的
"""
arr12 = np.random.rand(2,4)
arr12


"""
    np.random.randint:生成指定范围的随机整数
    参数解释:
        low:范围下限。包含
        high:范围上限。不包含
        size:数组的形状
"""
arr13 = np.random.randint(low=1,high=7,size=(2,3,4))
arr13


"""
    np.random.randn:生成随机小数,结果符合标准正态分布
    标准正态分布:也称之为高斯分布。均值mean=0,标准差std=1
"""
arr14 = np.random.randn(10,10,10)
arr14

数组的索引、切片

一维、二维、三维的数组如何索引?

  • 直接进行索引,切片
  • 二维数组[行索引开始:行索引结束:步长, 列索引开始:列索引结束:步长],含头不含尾

基本索引:

import numpy as np

# 创建一个 2x3 的数组
arr = np.array([[1, 2, 3], [4, 5, 6]])

# 访问第1行第2列的元素(注意:索引从0开始)
element = arr[0, 1]
print("第1行第2列的元素:", element)  # 输出: 2

# 访问第2行第3列的元素
element = arr[1, 2]
print("第2行第3列的元素:", element)  # 输出: 6

切片操作

二维数组:可以通过 [row, column] 进行索引和切片,提取特定的行、列或子矩阵。

三维数组:可以通过 [depth, row, column] 进行索引和切片,提取特定的层、行、列或子阵列。

import numpy as np

# 创建一个 7x7 的数组
# 二维数组[行索引开始:行索引结束:步长, 列索引开始:列索引结束:步长]
arr = np.array(
    [
        [10, 2, 3, 73, 8, 7, 6],
        [11, 5, 6, 74, 8, 9, 10],
        [22, 5, 6, 75, 8, 9, 10],
        [33, 5, 6, 76, 8, 9, 10],
        [44, 5, 6, 77, 8, 9, 10],
        [55, 5, 6, 78, 8, 9, 10],
        [66, 5, 6, 79, 8, 9, 10],
    ]
)

sub_array = arr[1:6:2, 0:6:3]
print(sub_array)

# 提取第1行和第2行的所有列
sub_array = arr[0:2, :]
print("第1行和第2行的所有列:\n", sub_array)

# 提取第2列和第3列的所有行
sub_array = arr[:, 1:3]
print("第2列和第3列的所有行:\n", sub_array)

# 提取第1行第2列到第3列的元素
sub_array = arr[0, 1:3]
print("第1行第2列到第3列的元素:", sub_array)
  • 三维数组索引方式:
# 三维
a1 = np.array([[[1,2,3],[4,5,6]], [[12,3,34],[5,6,7]]])
# 返回结果
array([[[ 1,  2,  3],
        [ 4,  5,  6]],

       [[12,  3, 34],
        [ 5,  6,  7]]])

# 索引、切片
sub_array = a1[0, 0, 1]
print(sub_array) # 输出: 2

形状修改

ndarray.reshape(shape)

  • 修改前后元素个数不能变
arr2 = np.array([1, 2, 3, 4, 5, 6, 7, 8, 9])
arr2

# reshape前后的元素个数不能变,不能变多不能变少
# reshape中的-1表示Numpy自动的帮我们计算形状
# reshape还可以升维或者降维
arr3 = arr2.reshape(3,3)
arr3 = arr2.reshape(1,9)
arr3 = arr2.reshape(1,-1)
# arr3 = arr2.reshape(1,3,3) # 升维
arr3 = arr2.reshape(9,1,1) # 升维

# 下面的都是错误的写法
# arr3 = arr2.reshape(2,4)      # 元素个数少了
# arr3 = arr2.reshape(2,5)      # 元素个数多了
# arr3 = arr2.reshape(2,4.5)    # 传递小数

arr3

np.resize(数组对象, new_shape)

  • 修改前后元素个数可以不同
# 【了解】resize:调整形状前后的元素个数可以不一致
arr3 = np.array([1, 2, 3, 4, 5, 6, 7, 8, 9])
arr3

# 注意:resize需要通过np来进行调用,不能直接通过具体的array数组调用
arr4 = np.resize(a=arr3,new_shape=(3,3))
arr4 = np.resize(a=arr3,new_shape=(3,4))
arr4 = np.resize(a=arr3,new_shape=(3,2))
arr4

ndarray.T

  • 数组的转置
  • 将数组的行、列进行互换
import numpy as np

# 创建一个 2x3 的二维数组
arr = np.array([[1, 2, 3],
                [4, 5, 6]])

# 对数组进行转置
transposed_arr = arr.T

print("原始数组:\n", arr)
print("转置后的数组:\n", transposed_arr)

运行结果
原始数组:
 [[1 2 3]
  [4 5 6]]
转置后的数组:
 [[1 4]
  [2 5]
  [3 6]]

类型修改

ndarray.astype(type)

  • 返回修改了类型之后的数组
import numpy as np

# 创建一个浮点数类型的数组
arr = np.array([1.1, 2.2, 3.3, 4.4, 5.5])

# 使用 .astype(np.int32) 将数组的元素类型转换为 int32
arr_int32 = arr.astype(np.int32)

print("原始数组:", arr)
print("原始数组的类型:", arr.dtype)

print("转换后的数组:", arr_int32)
print("转换后的数组类型:", arr_int32.dtype)

ndarray.tobytes()

  • 构造包含数组中原始数据字节的Python字节
arr = np.array([[[1, 2, 3], [4, 5, 6]], [[12, 3, 34], [5, 6, 7]]])
arr.tobytes()

为什么转二进制?方便网络传输

数组的去重

np.unique()

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

四、ndarray运算

掌握内容

all
any
argmax:与idxmax的作用完全一致,取最大值对应的索引

逻辑运算

# 过滤出分数超过60分,并且小于90分的成绩
score = np.random.randint(40, 100, (10, 5))
six_stu = score[6:, :]
six_stu

# 过滤出分数超过60分,并且小于90分的成绩。将对应成绩设置为1
six_stu[ (six_stu>60) & (six_stu<90)] = 1
six_stu

通用判断函数

  • np.all()

    当你需要检查数组中的所有元素是否都满足条件时使用,如果所有元素都满足条件,返回 True,否则返回 False

  • np.any()

    当你需要检查数组中是否至少有一个元素满足条件时使用,如果有一个元素满足条件,返回 True,否则返回 False

# 判断前4名同学的成绩[0:4, :]是否全及格
four_stu = score2[0:4, :]
four_stu>=60

# 所有学生的所有成绩,全部都>=60分的时候,结果才是True;否则,只要出现一个成绩<60,结果就是False
np.all(four_stu>=60)

# 判断前4名同学的成绩[0:4, :]是否有大于90分的
# 只要能够找出一个值满足条件,结果就是True;否则,全部都不满足的时候才是False
np.any(four_stu>90)

np.where(三元运算符)

通过使用np.where能够进行更加复杂的运算

  • np.where() => 类似Python中的if…else结构

  • 复合逻辑需要结合np.logical_and和np.logical_or使用

np.random.seed(523)
score3 = np.random.randint(40, 100, (10, 5))
score3

# 判断前四名学生,前四门课程中,成绩中大于60的置为1,否则为0
arr1 = np.where(score3[:4, :4]>60, 1,0)
arr1

# 判断前四名学生,前四门课程中,成绩中大于60且小于90的换为1,否则为0
# 写法一:推荐
arr2 = np.where((score3[:4, :4]>60) & (score3[:4, :4]<90), 1,0)

# 写法二:使用函数包起来
arr2 = np.where(np.logical_and(score3[:4, :4]>60, score3[:4, :4]<90), 1,0)
arr2

# 判断前四名学生,前四门课程中,成绩中大于90或小于60的换为1,否则为0
# 写法一:推荐
arr3 = np.where((score3[:4, :4]<60) | (score3[:4, :4]>90), 1,0)

# 写法二:使用函数包起来
arr3 = np.where(np.logical_or(score3[:4, :4]<60, score3[:4, :4]>90), 1,0)
arr3

统计运算

如果想要知道学生成绩最大的分数,或者做小分数应该怎么做?

统计指标

在数据挖掘/机器学习领域,统计指标的值也是我们分析问题的一种方式。常用的指标如下:

  • min(a, axis)
    • Return the minimum of an array or minimum along an axis.
  • max(a, axis])
    • Return the maximum of an array or maximum along an axis.
  • median(a, axis)
    • Compute the median along the specified axis.
  • mean(a, axis, dtype)
    • Compute the arithmetic mean along the specified axis.
  • std(a, axis, dtype)
    • Compute the standard deviation along the specified axis.
  • var(a, axis, dtype)
    • Compute the variance along the specified axis.

var方差是衡量数据点离平均值的平方偏差程度。方差的值总是非负的,方差越大,数据越分散。

std标准方差是衡量数据点离平均值的平均偏差程度。值越小,数据越集中;值越大,数据越分散。

案例:学生成绩统计运算

score = np.random.randint(40, 100, (10, 5))

print("学生各科成绩的最大分:{}".format(np.max(temp, axis=0)))
print("学生各科成绩的最小分:{}".format(np.min(temp, axis=0)))
print("学生各科成绩波动情况:{}".format(np.std(temp, axis=0)))
print("学生各科成绩的平均分:{}".format(np.mean(temp, axis=0)))

==axis=0==:表示沿着行的方向(垂直向下)跨越,对每一列进行操作,结果是行数被修改了。

==axis=1==:表示沿着列的方向(水平向右)跨越,对每一行进行操作,结果是列数被修改了。

==该参数的使用和参数值含义,与Pandas中完全一样。==

如果需要统计出某科最高分对应的是哪个同学?

  • np.argmax(temp, axis=)
  • np.argmin(temp, axis=)
print("学生各科成绩最高分对应的学生下标:{}".format(np.argmax(temp, axis=0)))

五、数组间运算

掌握内容

矩阵运算
    np.matmul(矩阵A, 矩阵B)   或者  矩阵A@矩阵B
    前提:前一个矩阵的列数,与后一个矩阵的行数相同,才能计算。矩阵运算没有广播机制

数组与数的运算

arr = np.array([[1, 2, 3, 2, 1, 4], [5, 6, 1, 2, 3, 1]])
arr + 1
arr / 2

# 可以对比python列表的运算,看出区别 => 列表是整体操作,numpy是每个元素单独操作
a = [1, 2, 3, 4, 5]
a * 3

矩阵运算

矩阵运算的前提:前一个矩阵的列数,与后一个矩阵的行数相同,才能计算

"""
    矩阵乘法运算总结:
        1- A @ B = C,  A的列数 必须 与 B的行数 相同
        2- A[m行,n列] B[p行,q列],那么结果C的形状是[m行,q列]
"""

np.random.seed(520)
arr3 = np.random.randint(low=1,high=5,size=(2,4))
arr3


np.random.seed(520)
arr4 = np.random.randint(low=1,high=5,size=(4,3))
arr4


# 写法一:推荐。使用@符号
result_1 = arr3 @ arr4
# 写法二:使用matmul函数。matrix multiply
result_1 = np.matmul(arr3, arr4)
result_1

【了解】数组与数组的运算

广播机制总结:
    1- 是Numpy底层内部自动进行的一种机制,我们无法人为的控制
    2- 价值:实现形状不同数组之间的运算,核心就是通过广播机制自动的达到数组形状完全相同的前提要求

思考

arr1 = np.array([[1, 2, 3, 2, 1, 4], [5, 6, 1, 2, 3, 1]])   # 2 x 6
arr2 = np.array([[1, 2, 3, 4], [3, 4, 5, 6]])  # 2 x 4

上面这个能进行加法运算吗,结果是不行的!

广播机制

数组在进行加法运算时,要求数组的形状要完全相等的。当形状不相等的数组执行算术运算的时候,就会出现广播机制,该机制会对数组进行扩展,使数组的shape属性值一样,这样,就可以进行矢量化运算了。下面通过一个例子进行说明:

arr1 = np.array([[0],[1],[2],[3]])  # 4 x 1
arr1.shape
# (4, 1)

arr2 = np.array([1,2,3])  # 1 x 3
arr2.shape
# (3,)

arr1+arr2
# 结果是:
array([[1, 2, 3],
       [2, 3, 4],
       [3, 4, 5],
       [4, 5, 6]])

上述代码中,数组arr1是4行1列,arr2是1行3列。这两个数组要进行相加,按照广播机制会对数组arr1和arr2都进行扩展,使得数组arr1和arr2都变成4行3列。

下面通过一张图来描述广播机制扩展数组的过程:

image-20190620005224076

什么情况下才能进行广播机制:

  • 形状完全相等
    两个数组在该维度上的大小完全相同。
import numpy as np

# 数组 A: 形状 (2, 3)
A = np.array([[1, 2, 3],
              [4, 5, 6]])

# 数组 B: 形状 (2, 3)
B = np.array([[10, 20, 30],
              [40, 50, 60]])

# 运算
result = A + B

print("结果:\n", result)

运行结果:
[[11 22 33]
[44 55 66]]

  • 其中至少一个维度大小为 1
    两个数组中,至少有一个在该维度上的大小为 1。NumPy 会自动将这个大小为 1 的维度“拉伸”以匹配另一个数组。
import numpy as np

# 数组 A: 形状 (2, 3)
A = np.array([[1, 2, 3],
              [4, 5, 6]])

# 数组 B: 形状 (1, 3)
B = np.array([[10, 20, 30]])

# 运算
result = A + B

print("结果:\n", result)

运行结果:

[[11 22 33]
[14 25 36]]

  • 其中一个数组缺少该维度
    如果两个数组的维度数量不同,维度较少的数组在前面会被视为用 1 来填充,然后再进行比较。
    • 例如:形状为 (3, 4) 的数组和形状为 (4,) 的数组比较时,(4,) 会被视为 (1, 4),因此它们是兼容的。
import numpy as np

# 1. 创建一个形状: (3, 4)
arr1 = np.array([
    [1, 2, 3, 4],
    [5, 6, 7, 8],
    [9, 10, 11, 12]
])

# 2. 创建一个形状: (1,4)
arr2 = np.array([10, 20, 30, 40])

# 3. 进行加法运算
result = arr1 + arr2

print("运算结果:\n", result)

运行结果:
[[11 22 33 44]
[15 26 37 48]
[19 30 41 52]]

思考:下面两个ndarray是否能够进行加法运算?可以

arr1 = np.array([[1, 2, 3, 2, 1, 4], [5, 6, 1, 2, 3, 1]])   # (2, 6)
arr2 = np.array([[1], [3]])  # (2, 1)

本文为 程序员青阳 原创文章,遵循 CC BY-NC-SA 4.0 版权协议,转载请附上原文链接及本声明。

原文链接:https://heliufang.github.io/posts/fa288682/index.html