Numpy学习笔记(一)

一、numpy简介

NumPy(Numerical Python)是 Python 进行科学计算的一个扩展库,提供了
大量的函数和操作,主要用于对多维数组执行计算,它比 Python 自身的嵌套
列表结构要高效的多

二、创建数组

(一)从现有的数据创建

1、np.array(object, dtype=None)
  • object:array_like,类似于数组的对象。如果object是标量,则返回包含object的0维数组
  • data-type,数组所需的数据类型。如果没有给出,会从输入数据推断数据类型
  • 创建一个数组对象并返回(ndarray实例对象)

DTYPE常用值

DTYPE常用值描述
np.int8字节(-128 to 127)
np.int16整数(-32768 to 32767)
np.int32整数(-2147483648 to 2147483647)
np.int64整数(-9223372036854775808 to 9223372036854775807)
np.uint8无符号整数(0 to 255)
np.uint16无符号整数(0 to 65535)
np.uint32无符号整数(0 to 4294967295)
np.uint64无符号整数(0 to 18446744073709551615)
np.float16半精度浮点数
np.float32单精度浮点数
np.float64双精度浮点数

NDARRAY常用属性

NDARRAY常用属性描述
ndarray.ndim即轴的数量或维度的数量
ndarray.shape数组的形状
ndarray.size数组元素的总个数 (shape相应元组相乘)
ndarray.dtypendarray 对象的元素类型
ndarray.itemsizendarray 对象中每个元素的大小,以字节为单位
 ndarray.shape  数组的形状 (一维数组的shape (m,n) 如 (3,) 表示这是一维数组,3表示一维数组有3个元素;  (2,3)表示是二维数组,2表示二维数组有2行(第一个维度有2个元素),3表示每行有3个元素(表示一行有3个元素) ) 
# 创建数组
arr = np.array([[1, 2, 3], [4, 5, 9]])
print(arr) 
#[[1 2 3]
# [4 5 9]]


#打印数组维度
print(arr.ndim)
# 2

#数组形状
print(arr.shape)
#(2, 3)

#数组元素总个数
print(arr.size) 
# 6

#对象的元素类型
print(arr.dtype)
#int32

#ndarray 对象中每个元素的大小
print(arr.itemsize)
# 4

np.array()函数接受一个可迭代对象作为输入,并将其转换成一个numpy数组。

arr1 = np.array((1, 2, 3))
print(arr1)
# [1 2 3]
arr2 = np.array(range(1, 5))
print(arr2)
# [1 2 3 4]
2、np.asarray(a, dtype=None)

类似于 np.array,主要区别是当 a是 ndarray 且 dtype 也匹配时,
np.asarray不执行复制操作,而 np.array 仍然会复制出一个副本,占
用新的内存

obj = [1, 2, 3] # a是array_like
# obj = np.array([1, 2, 3]) # a是ndarray
arr1 = np.array(obj)
arr2 = np.asarray(obj)
obj[1] = 4

print(obj)
# [1, 4, 3]

print(arr1)
# [1 2 3]

print(arr2)
# [1 2 3]
3、np.copy(a)
  • a: array_like,类似于数组的对象。
  • 返回给定对象的数组副本
a1 = [1, 2, 3]
arr1 = np.copy(a1)
a1[1] = 5

print(arr1)
# [1 2 3]
4、ndarray.copy()

对象方法,返回数组的副本

arr = np.array([1, 2, 3])
print(arr.copy())
# [1 2 3]
5、np.fromiter(iterable, dtype, count=-1)
  • iterable:可迭代对象
  • dtype:返回数组的数据类型
  • count:读取的数据数量,默认为-1,表示读取所有数据
  • 从可迭代对象创建一个新的一维数组并返回
iterable = (x * x for x in range(5))
print(np.fromiter(iterable, dtype=int, count=-1))

# [ 0  1  4  9 16]

 

(二)从形状或值创建

1、np.empty(shape, dtype=np.float64)
  • 返回给定形状和类型且未初始化的新数组
print(np.empty((2, 3), dtype=np.int16))

# [[77 75 76]
#  [95 86 69]]
2、np.empty_like(prototype, dtype=None)
  • prototype:array_like,类似于数组的对象
  • dtype:如果指定该参数,将会覆盖结果的数据类型
  • 返回形状和类型与给定 prototype 相同的新数组
a = np.array([[1, 2, 3], [4, 5, 6]], dtype=np.int32)
print(np.empty_like(a))

# [[-1 -1  2]
#  [ 0  0  0]]
3、np.zeros(shape, dtype=np.float64)
  • 返回给定形状和类型的新数组,并用零填充
print(np.zeros((2, 3), dtype=np.int16))

#[[0 0 0]
# [0 0 0]]
4、np.zeros_like(a, dtype=None)
  • a:array_like
  • dtype:如果指定该参数,将会覆盖结果的数据类型
  • 返回一个与给定 a 具有相同形状和类型的零数组。
arr = ([1, 2, 3], [4, 5, 6])
print(np.zeros_like(arr))

# [[0 0 0]
#  [0 0 0]]
5、np.ones(shape, dtype=np.float64)
  • 返回给定形状和类型的新数组,并用1填充
print(np.ones((2, 3), dtype=np.int16))

# [[1 1 1]
#  [1 1 1]]
6、np.ones(shape, dtype=np.float64)
  • a:array_like
  • dtype:如果指定该参数,将会覆盖结果的数据类型
  • 返回一个与给定 a 具有相同形状和类型的1构成的数组。
a = ([1, 2, 3], [4, 5, 6])
print(np.ones_like(a))

# [[1 1 1]
#  [1 1 1]]
7、np.full(shape, fill_value, dtype=None)
  • 返回给定形状和类型的新数组,并用 fill_value 填充
print(np.full((2, 3), 9, dtype=np.int8))

#[[9 9 9]
#  [9 9 9]]
8、np.full_like(a, fill_value, dtype=None)
  • a:array_like
  • dtype:如果指定该参数,将会覆盖结果的数据类型
  • 返回一个与给定 a 具有相同形状和类型的 fill_value 填充的数组
 a = ([1, 2, 3], [4, 5, 6])
 print(np.full_like(a, 6))
 
#[[6 6 6]
# [6 6 6]]
9、np.eye(N, M=None, k=0, dtype=np.float64)
  • N:输出数组的行数
  • M:输出数组的列数。如果为None,则默认为N
  • k:对角线的索引,默认为0,表示主对角线,正值表示上对角线,负值表示下对角线
  • dtype:数组的数据类型
print(np.eye(3, 4, 0, dtype=np.int8))

# [[1 0 0 0]
#  [0 1 0 0]
#  [0 0 1 0]]
10、np.eye(N, M=None, k=0, dtype=np.float64)
  • 返回 n*n 的单位数组(主对角线为1,其他元素为0的方形数组)
  • 对角线为1,其他地方为0(单位矩阵)
print(np.identity(3, dtype=np.int8))

# [[1 0 0]
#  [0 1 0]
#  [0 0 1]]

 

(三)从数值范围创建数组

1、np.arange([start,] stop[, step,], dtype=None)
  • 返回一个包含从 start 到 stop(不包括)的等差数列的数组
  • start:开始值,默认为0
  • stop:结束值
  • step:步长,默认为1
  • dtype:数组的数据类型
print(np.arange(1, 10, 2, dtype=np.int8))

# [1 3 5 7 9]
2、np.linspace(start, stop, num=50, endpoint=True, retstep=False, dtype=None)
  • num:生成的样本数量
  • endpoint:如果为 True, stop 为最后一个样本。否则,不包括在内
  • retstep:如果为 True,返回 (samples, step), step 是样本之间的间隔
  • dtype:如果没有给出dtype,则从 start 和 stop 推断数据类型。推断出的 dtype 永远不会是整数;即使参数会产生一个整数数组,也会选择 np.float64
  • 把给定区间分成 num 个均匀间隔的样本,构成数组并返回(等差数列
print(np.linspace(1, 10, num=4, endpoint=False, retstep=True, dtype=np.float32))

# (array([1.  , 3.25, 5.5 , 7.75], dtype=float32), 2.25)
3、np.logspace(start, stop, num=50, endpoint=True, base=10.0,dtype=None)
  • start:序列的起始值为:base ** start
  • stop:序列的终止值为:base ** stop
  • num:生成的样本数量
  • endpoint:如果为 True, stop 为最后一个样本。否则,不包括在内
  • 对数 log 的底数
  • dtype:如果没有给出dtype,则从 start 和 stop 推断数据类型。推断出的 dtype 永远不会是整数;即使参数会产生一个整数数组,也会选择 np.float64
  • 把给定区间分成 num 个按对数尺度均匀间隔的样本,构成数组并返回(等比数列
print(np.logspace(2, 3, num=4, endpoint=False, base=10, dtype=np.int32))

# [100 177 316 562]

三、广播机制

 
        NumPy的广播(broadcasting)机制是NumPy库中的一种强大的功能,它允许NumPy在执行数组运算时自动扩展数组的维度,从而可以在不同形状的数组之间进行数学运算。这种机制极大地简化了数组之间的运算,并提高了运算的效率。
 

广播的基本规则如下:

  1. 如果两个数组的维度数不同,那么在维度较小的数组形状左侧补1,直到两个数组的形状长度相同。例如,形状为(3,)的数组和形状为(2,3)的数组进行广播时,前者会被视为(1,3)的形状。
  2. 从最后一个维度(即最右边的维度)开始比较两个数组的形状,对应维度上的值必须相等,或者其中一个值为1。如果满足这个条件,那么就可以进行广播。否则,无法进行广播。
  3. 广播会在所有长度为1的维度上进行,生成的新数组形状是原数组形状在非1维度上的最大值。

广播的前提:

  • 后缘维度相同或者不同的维度有1,可以广播
a = np.arange(24).reshape((2, 3, 4))
b = np.arange(12).reshape((3, 4))
c = np.arange(4).reshape((1, 4))
d = np.arange(4).reshape(4)
e = np.arange(12).reshape((1, 3, 4))
f = np.arange(6).reshape((2, 3, 1))
g = np.arange(2).reshape((2, 1, 1))
h = np.arange(2).reshape((1, 2, 1, 1))
i = np.arange(10).reshape((5, 2, 1, 1))

a与b、c、d、e的后缘维度相同

print((a + b).shape)
print((a + c).shape)
print((a + d).shape)
print((a + e).shape)

# (2, 3, 4)
# (2, 3, 4)
# (2, 3, 4)
# (2, 3, 4)

a与f、g、h、i的后缘维度不同,但其维度是1

print((a + f).shape)
print((a + g).shape)
print((a + h).shape)
print((a + i).shape)

# (2, 3, 4)
# (2, 3, 4)
# (1, 2, 3, 4)
# (5, 2, 3, 4)

四、索引和切片

 
数组的索引和切片与 Python 中序列的索引和切片区别:

数组的索引和切片与 Python 中序列的索引和切片操作基本类似,不同点在于:
    ①数组切片不会复制内部数组数据,只会生成原始数据的新视图
    ②数组支持多维数组的多维索引和切片

    需要注意的是,切片返回的是原始数组的一个视图(view),这意味着返回的数组与原始数组共享相同的数据内存块。对切片所做的任何修改都会反映到原始数组中(除非进行了数据复制,比如通过修改数组形状或数据类型。

切片语法:
基本语法是使用冒号(:)来指定开始索引、结束索引和步长
array[start:stop:step]

  • start:开始索引(包含),默认为0。
  • stop:结束索引(不包含),默认为数组长度。
  • step:步长,即选择元素时的间隔,默认为1。

注意:索引是前闭后开的区间 ‘[ )’

1. 一维数组索引和切片

索引:

    array = np.arange(2, 10)
    print(array) # [2 3 4 5 6 7 8 9]
    
    item = array[1]
    print(item) # 3
 

切片:

    part = array[-2:1:-1]
    print(part) # [8 7 6 5 4]
    
    array[1] = 33
    array[3:] = [55, 66, 77, 88, 99]
    
    print(item) # 3
    print(part) # [88 77 66 55  4]

2. 多维数组切片

索引:

 lis = [[1, 2], [3, 4], [5, 6]]
 arr = np.array(lis)
 print(arr)
 
# [[1 2]
#  [3 4]
#  [5 6]]
 print(arr[1, 0]) 
 
 # 3 

使用基本索引,arr[1, 0]表示选择第2行(索引为1,因为索引是从0开始的)和第1列(索引为0)的元素。输出是3。

print(arr[1][0])

 # 3

这行代码与上一行在功能上是等效的,但使用了不同的索引方式。arr[1]首先选择了第2行,得到一个一维数组[3, 4],然后[0]从这个一维数组中选择了第1个元素,即3

 
切片:

print(arr[:2, 1:2])

# [[2]  
#  [4]]

    这里使用了切片。arr[:2]选择了前两行,形成一个形状为(2, 2)的子数组:
[[1 2]
[3 4]]
然后,1:2选择了这些行的第2列(Python中的切片是左闭右开的),但是因为你使用的是1:2(起始索引是1,结束索引是2,不包括2),所以实际上只会选择索引为1的列,即第2列。
但是,由于你选择的范围只包含一个元素(从索引1到索引2,但不包括2),所以结果是一个形状为(2, 1)的数组:

print(arr[:2][1:2])

#  [[3 4]]

    这行代码首先使用arr[:2]选择了前两行,得到一个形状为(2, 2)的子数组。然后,[1:2]对这个子数组进行切片,选择了第2行(在子数组中,不是原始数组中的第2行,而是第1行,因为子数组已经只有两行)。
所以结果是一个形状为(1, 2)的数组,只包含原数组的第二行:[[3 4]]

总结:

  • arr[1, 0]和arr[1][0]都选择了原数组的第二行第一列的元素。
  • arr[:2, 1:2]选择了原数组前两行的第二列的元素,但由于切片范围只包含一个元素,所以结果是一个列向量。
  • arr[:2][1:2]首先选择了原数组的前两行,然后从这些行中选择了第二行(在子数组中的位置),所以结果是一个单行矩阵。

3.高级索引

 
在NumPy中,当你使用列表或数组作为索引时,你实际上是在执行高级索引。这种索引方式允许你通过指定一个索引数组来选择多个元素,这些元素可以来自数组的任何位置,并且不必是连续的。
 
① 使用单个数组作为索引

 x = np.array([[1, 2], [3, 4], [5, 6]])
 print(x[[1, 2]]) # 等价于x[1]和x[2]组成的数组

#  [[3 4]
#   [5 6]]

x[[1, 2]] 表示你想从数组 x 中提取索引为 1 和 2 的行。由于 Python 中的索引是从 0 开始的,所以索引 1 对应的是第 2 行,索引 2 对应的是第 3 行。因此,这段代码会输出一个包含原始数组 x 中第 2 行和第 3 行的新数组。
 
 
② 使用两个数组作为索引

 print(x[[0, 1, 2], [0, 1, 0]]) # 等价于x[0, 0]、x[1, 1]和x[2, 0]组成的数组
 
 # [1 4 5]

当你使用两个索引数组进行高级索引时,第一个数组指定了行索引,第二个数组指定了列索引。
这两个数组的长度必须相同,因为它们是成对使用的:第一个元素来自第一个数组的行索引和第二个数组的列索引,
第二个元素来自第二个数组的行索引和第二个数组的列索引,依此类推。

  • 从第 0 行(索引为 0)提取第 0 列的元素,即 x[0, 0],得到 1。
  • 从第 1 行(索引为 1)提取第 1 列的元素,即 x[1, 1],得到 4。
  • 从第 2 行(索引为 2)提取第 0 列的元素,即 x[2, 0],得到 5。
     
     
    ③ 使用布尔数组作为索引
 print(x[[True, False, True]])
 
# [[1 2]
#  [5 6]]

使用布尔数组作为索引是一种高级索引的形式,允许你根据布尔条件选择数组中的元素。布尔数组中的每个元素(True 或 False)对应于原始数组中相应位置的元素是否应该被选中。
 
 
④ 使用比较运算符索引

print(x < 4)

# [[ True  True]
#  [ True False]
#  [False False]]

在NumPy中,当你对数组使用比较运算符(如 <、>、<=、>=、==、!=)时,你会得到一个与原始数组形状相同的布尔数组,其中的每个元素都是原始数组中对应元素与给定值比较的结果(True 或 False)。

print(x[x < 4])

# [1 2 3]

print(x[np.array([[True, True], [True, False], [False,False]])]) 

# [1 2 3]

NumPy 会提取所有布尔值为 True 的位置对应的元素,并将它们展平为一个一维数组。所以输出将会是[1 2 3]

  • 23
    点赞
  • 24
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值