python.numpy.day14

3.数据类型

NumPy 提供了比 Python 更加丰富的数据类型,如下所示:

序号数据类型语言描述
1bool_布尔型数据类型(True 或者 False)
2int_默认整数类型,类似于 C 语言中的 long,取值为 int32 或 int64
3intc和 C 语言的 int 类型一样,一般是 int32 或 int 64
4intp用于索引的整数类型(类似于 C 的 ssize_t,通常为 int32 或 int64)
5int8代表与1字节相同的8位整数。值的范围是-128到127
6int16代表 2 字节(16位)的整数。范围是-32768至32767
7int32代表 4 字节(32位)整数。范围是-2147483648至2147483647
8int64表示 8 字节(64位)整数。范围是-9223372036854775808至9223372036854775807
9uint81字节(8位)无符号整数
10uint162 字节(16位)无符号整数
11uint324 字节(32位)无符号整数
12uint648 字节(64位)无符号整数
13float_float64 类型的简写
14float16半精度浮点数,包括:1 个符号位,5 个指数位,10个尾数位
15float32单精度浮点数,包括:1 个符号位,8 个指数位,23个尾数位
16float64双精度浮点数,包括:1 个符号位,11 个指数位,52个尾数位
17complex_复数类型,与 complex128 类型相同
18complex64表示实部和虚部共享 32 位的复数
19complex128表示实部和虚部共享 64 位的复数
20str_表示字符串类型,等价于unicode_
21bytes_表示字节串类型,基于字节
22string_表示字节串类型,等价于bytes_,基于字节,NumPy 2.0以后版本被移除,使用bytes_代替
23unicode_表示字节串类型,基于字符,NumPy 2.0以后版本被移除,使用str_`代替

3.1 数据类型对象

数据类型对象(Data Type Object)又称 dtype 对象,是用来描述与数组对应的内存区域如何使用。

1.可以在创建数组时指定 dtype 参数来定义数组中元素的数据类型。

import numpy as np

# 创建一个 int32 类型的数组
arr_int = np.array([1, 2, 3], dtype=np.int32)
print(arr_int.dtype)  # 输出: int32

# 创建一个 float64 类型的数组
arr_float = np.array([1, 2, 3], dtype=np.float64)
print(arr_float.dtype)  # 输出: float64

2.可以使用数组的 dtype 属性来获取数组中元素的数据类型。

#artype():转换数据类型
a = np.array([1,2,3])
print(a.dtype)
b = a.astype(np.float64)
print(b)
print(b.dtype)

4.数组属性

4.1 shape

返回一个元组,元组中的每个元素表示数组在对应维度上的大小。元组的长度等于数组的维度数。

shape 属性功能:

  1. 返回一个由数组维度构成的元组

  2. 通过赋值,可以用来调整数组维度的大小

#shape:返回数组的形状,是一个元组
#shape也可以通过赋值修改形状,修改后的形状会影响原数组
a = np.array([1,2,3,4,5,6,7,8,9],order= 'F')
print(a)
print(a.shape)
a.shape=(3,1,3)
print(a)

如果使用shape属性修改数组的形状,则修改的是原数组的形状,reshape修改数组的形状会返回一个新数组,不修改原数组的形状。

4.2 数组维度

数组的维度就是一个数组中的某个元素,当用数组下标表示的时候,需要用几个数字来表示才能唯一确定这个元素,这个数组就是几维

ndmin 是 NumPy 中用于创建数组时指定最小维度的参数。它通常在 numpy.array() 函数中使用。通过 ndmin,你可以确保生成的数组至少具有指定的维度。

ndim 是 NumPy 数组的一个属性,用于返回数组的维度数(即数组的秩)。它表示数组有多少个维度。

案例:

import numpy as np

# 指定/查看数组维度
def ndmin_test():
    threeArray = np.array([1,2,3,4],ndmin=2)
    print("ndmin 指定数组:",threeArray)
    print("ndmin 指定数组:",type(threeArray))
    print("ndim 查看维度:",threeArray.ndim)

5.切片

ndarray 对象的内容可以通过索引或切片来访问和修改,与 Python 中 list 的切片操作一样;

5.1 slice()

在 Python 中,slice 可以作为一个对象来使用。你可以创建一个 slice 对象,然后使用它来获取序列的片段。

参数:

  • start 是切片开始的位置(包含该位置)。

  • stop 是切片结束的位置(不包含该位置)。

  • step 是切片的步长,即选取元素的间隔

import numpy as np

def two():
    array_one = np.array([[1, 2, 3], [4, 5, 6]])
    print(array_one)
    print(array_one[..., 1])  # 第2列元素
    print(array_one[1,...]) # 第2行元素
    print(array_one[1:2, 1:2])  # 第2行第2列元素
    print(array_one[1:2])
    print(array_one[..., 1:])  # 第2列及剩下的所有元素

 

冒号 : 的作用

  • 表示范围: 冒号用于表示一个范围。例如,array[1:3] 表示从索引 1 到索引 3(不包括 3)的元素。

  • 表示所有元素: 单独使用冒号表示所有元素。例如,array[:, 1] 表示所有行的第 1 列。

  • 步长: 双冒号后面可以跟一个步长值,表示每隔多少个元素取一个。例如,array[::2] 表示每隔一个元素取一个。

注:冒号对于一维数组按索引号截取,二维数组按行和列截取。

省略号 ... 的作用

  • 表示所有维度: 省略号用于表示数组的所有维度。例如,array[..., 1] 表示取所有行的第 1 列。

  • 简化多维切片: 在多维数组中,省略号可以简化切片操作,避免显式地写出所有维度的索引。

注意:slice返回的数组是原数组的一个视图,修改数据会影响原数组中的数据。

import numpy as np

array_one = np.array([[1, 2, 3], [4, 5, 6]])
array_two = array_one[..., 1]
print(array_two)
array_two[0] = 100
print(array_two)
print(array_one)

6.高级索引

NumPy 中的高级索引指的是使用整数数组、布尔数组或者其他序列来访问数组的元素。相比于基本索引,高级索引可以访问到数组中的任意元素,并且可以用来对数组进行复杂的操作和修改。

6.1 整数数组索引

整数数组索引是指使用一个数组来访问另一个数组的元素。这个数组中的每个元素都是目标数组中某个维度上的索引值。

适用于需要访问非连续元素或特定位置元素的场景。

注意:返回的新数组是一个副本,修改它不会影响原数组。

案例:

import numpy as np

def one():
    array_one = np.array([[1,2,3],[4,5,6]])
    print(array_one)
    # [0,1,0]代表行索引、[0,1,2]代表列索引;即取出索引坐标 (0,0)、(1,1)、(0,2) 的元素
    array_one = array_one[[0,1,0],[0,1,2]]
    print(array_one)

6.2 布尔索引

布尔索引通过布尔运算(如:比较运算符)来获取符合指定条件的元素的数组。

import numpy as np

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

# 使用布尔索引筛选大于 5 的元素
bool_idx = arr > 5
print(bool_idx)
# 输出:
# [[False False False]
#  [False False  True]
#  [ True  True  True]]

# 使用布尔索引获取满足条件的元素
result = arr[bool_idx]
print(result)  # 输出: [6 7 8 9]

 案例3:切片布尔索引

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

# 1. 索引第3个元素大于3的所有行
print(data[data[:, 2] > 3])

# 2. 索引第3行 值大于3 的所有的元素 所在的列
print(data[:, data[1] > 3])

使用逻辑运算符(如 &、|、~)组合多个条件。

import numpy as np

# 创建一个一维数组
arr = np.array([1, 2, 3, 4, 5, 6, 7, 8, 9, 10])

# 使用布尔索引筛选大于 5 且小于 9 的元素
bool_idx = (arr > 5) & (arr < 9)
print(bool_idx)  # 输出: [False False False False False  True  True  True False False]

# 使用布尔索引获取满足条件的元素
result = arr[bool_idx]
print(result)  # 输出: [6 7 8]

7.广播(*)

广播(Broadcast)是 numpy 对不同形状(shape)的数组进行数值计算的方式, 对数组的算术运算通常在相应的元素上进行。这要求维数相同,且各维度的长度相同,如果不相同,可以通过广播机制,这种机制的核心是对形状较小的数组,在横向或纵向上进行一定次数的重复,使其与形状较大的数组拥有相同的维度。

广播规则

  1. 维度匹配:如果两个数组的维度数不同,维度数较少的数组会在前面补上长度为 1 的维度。

# 示例 1:维度匹配
a = np.array([[1, 2, 3], [4, 5, 6]])  # 形状: (2, 3)
b = np.array([10, 20, 30])            # 形状: (3,)
c = a + b
print(c)
# 输出:
# [[11 22 33]
#  [14 25 36]]

 形状匹配:如果两个数组在某个维度上的长度不同,但其中一个数组在该维度上的长度为 1,则该数组会沿着该维度进行广播。

# 示例 2:形状匹配
# 1.d是2维数组,e是一维数组,e自动广播为2为数组:[[10 20 30] [10 20 30]],形状为(2,3)
# 2.d和e在行维度上都为2,d在列维度上是一维,自动广播为:[[1 1 1] [2 2 2]],形状为(2,3)
d = np.array([[1], [2]])  # 形状: (2, 1)
e = np.array([10, 20, 30])  # 形状: (3,)
f = d + e
print(f)
# 输出:
# [[11 21 31]
#  [12 22 32]]
  1. 不匹配:如果两个数组在某个维度上的长度既不相同也不为 1,则广播失败,抛出 ValueError。

import numpy as np

# 创建一个二维数组
arr2d = np.array([[1, 2, 3], [4, 5, 6], [7, 8, 9]])

# 创建一个形状为 (2, 3) 的二维数组
arr2d_broadcast = np.array([[10, 20, 30], [40, 50, 60]])

# 尝试相加
try:
    result = arr2d + arr2d_broadcast
except ValueError as e:
    print(e)  # 输出: operands could not be broadcast together with shapes (3,3) (2,3)

8.遍历数组

8.1 遍历数组的第一维度

for i in arr: 遍历数组的第一维度,即按行或列的顺序逐个访问元素。

返回的是数组的子数组(如行或列),而不是单个元素。

8.2 nditer逐个访问元素

nditer 是 NumPy 中的一个强大的迭代器对象,用于高效地遍历多维数组。nditer 提供了多种选项和控制参数,使得数组的迭代更加灵活和高效。

控制参数

nditer 提供了多种控制参数,用于控制迭代的行为。

1.order 参数

order 参数用于指定数组的遍历顺序。默认情况下,nditer 按照 C 风格(行优先)遍历数组。

  • 2.flags 参数

    flags 参数用于指定迭代器的额外行为。

  • multi_index: 返回每个元素的多维索引。

  • external_loop: 返回一维数组而不是单个元素,减少函数调用的次数,从而提高性能。

    # 创建一个三维数组
        arr = np.array([[[1, 2], [3, 4]], [[5, 6], [7, 8]]])
    
        # 使用 nditer 遍历数组并获取多维索引
        it = np.nditer(arr, flags=['multi_index'])
        for x in it:
            print(f"Element: {x}, Index: {it.multi_index}")
    
    # 输出:
    # Element: 1, Index: (0, 0, 0)
    # Element: 2, Index: (0, 0, 1)
    # Element: 3, Index: (0, 1, 0)
    # Element: 4, Index: (0, 1, 1)
    # Element: 5, Index: (1, 0, 0)
    # Element: 6, Index: (1, 0, 1)
    # Element: 7, Index: (1, 1, 0)
    # Element: 8, Index: (1, 1, 1)
    
    
    # 创建一个二维数组
    arr = np.array([[1, 2, 3], [4, 5, 6]])
    # 使用外部循环遍历数组,列优先
    for x in np.nditer(arr, flags=['external_loop'], order='F'):
        print(x)
    # 输出:
    # [1 4]
    # [2 5]
    # [3 6]
    # 注意:external_loop 和 order='F' 一起使用时,会将每列的元素打包成一个数组返回。
    
    import numpy as np
    
    arr = np.array([[1, 2, 3], [4, 5, 6]])
    # 使用外部循环遍历数组,行优先
    for x in np.nditer(arr, flags=['external_loop'], order='C'):
        print(x)
    # 输出:
    [1 2 3 4 5 6]
    # 注意:external_loop 会将所有元素打包成一个数组返回,而不是按行打包。

    9.数组操作

    9.1 数组变维

  • 函数名称函数介绍
    reshape在不改变数组元素的条件下,修改数组的形状
    flat属性返回是一个迭代器,可以用 for 循环遍历其中的每一个元素
    flatten以一维数组的形式返回一份数组的副本,对副本的操作不会影响到原数组
    ravel返回一个连续的扁平数组(即展开的一维数组),与 flatten不同,它返回的是数组视图(修改视图会影响原数组)

    9.1.1 reshape

    reshape() 函数允许你在不改变数组数据的情况下,改变数组的维度。

    reshape() 返回的是一个新的数组,原数组的形状不会被修改。reshape() 可以用于多维数组,例如将一个一维数组重塑为二维数组。

    但是,reshape后产生的新数组是原数组的一个视图,即它与原数组共享相同的数据,但可以有不同的形状或维度,且对视图的修改会直接影响原数组。

    元素总数必须匹配:新形状中的元素总数必须与原数组中的元素总数相同。

    例如,一个长度为6的一维数组可以被重塑为 (2, 3) 或 (3, 2),表示原数组被重塑为2行3列或3行2列的数组,但不能被重塑为 (2, 2)。

    import numpy as np
    
    # 数组变维
    def reshape_test():
        oneArray = np.array([1,2,3,4,5,6])
        print("oneArray 原数组内容:",oneArray)
        print("oneArray 原数组维度:",oneArray.ndim)
        oneArray = oneArray.reshape((3,2))
        print("oneArray 新数组内容:",oneArray)
        print("oneArray 新数组维度:",oneArray.ndim)

    -1 作为占位符:你可以使用 -1 作为占位符,让 numpy 自动计算某个维度的大小。

import numpy as np

# 数组变维
def reshape_test():
    oneArray = np.array([1,2,3,4,5,6])
    print("oneArray 原数组内容:",oneArray)
    print("oneArray 原数组维度:",oneArray.ndim)
    oneArray = oneArray.reshape((3,-1))
    print("oneArray 新数组内容:",oneArray)
    print("oneArray 新数组维度:",oneArray.ndim)

 

9.1.2 flat

返回一个一维迭代器,用于遍历数组中的所有元素。无论数组的维度如何,ndarray.flat属性都会将数组视为一个扁平化的一维数组,按行优先的顺序遍历所有元素。

import numpy as np

def flat_test():
    array_one = np.arange(4).reshape(2,2)
    print("原数组元素:")
    for i in array_one:
        print(i,end=" ")
    print()
    print("使用flat属性,遍历数组:")
    for i in array_one.flat:
        print(i,end=" ")

9.1.3 flatten()

用于将多维数组转换为一维数组。flatten() 返回的是原数组的一个拷贝,因此对返回的数组进行修改不会影响原数组。

语法:

9.1.4 ravel()

用于将多维数组转换为一维数组。与 flatten() 不同,ravel() 返回的是原数组的一个视图(view),而不是副本。因此,对返回的数组进行修改会影响原数组。

语法:

9.2 数组转置

函数名称说明
transpose将数组的维度值进行对换,比如二维数组维度(2,4)使用该方法后为(4,2)
ndarray.T与 transpose 方法相同
import numpy as np

def transpose_test():
    array_one = np.arange(12).reshape(3, 4)
    print("原数组:")
    print(array_one)
    print("使用transpose()函数后的数组:")
    print(np.transpose(array_one))


def T_test():
    array_one = np.arange(12).reshape(3, 4)
    print("原数组:")
    print(array_one)
    print("数组转置:")
    print(array_one.T)

 

9.3 升维和降维

多维数组(也称为 ndarray)的维度(或轴)是从外向内编号的。这意味着最外层的维度是轴0,然后是轴1,依此类推。

函数名称参数说明
expand_dims(arr, axis)arr:输入数组 axis:新轴插入的位置在指定位置插入新的轴(相对于结果数组而言),从而扩展数组的维度
squeeze(arr, axis)arr:输入数的组 axis:取值为整数或整数元组,用于指定需要删除的维度所在轴,指定的维度值必须为 1 ,否则将会报错,若为 None,则删除数组维度中所有为 1 的项删除数组中维度为 1 的项

案例1:增加数组维度

import numpy as np

# 创建一个一维数组
a = np.array([1, 2, 3])
print(a.shape)  # 输出: (3,)

# 在第 0 维插入新维度
b = np.expand_dims(a, axis=0)
print(b)
# 输出:
# [[1 2 3]]
print(b.shape)  # 输出: (1, 3)

# 在第 1 维插入新维度
c = np.expand_dims(a, axis=1)
print(c)
# 输出:
# [[1]
#  [2]
#  [3]]
print(c.shape)  # 输出: (3, 1)

案例2:适应广播操作

# 创建一个一维数组
a = np.array([1, 2, 3])

# 创建一个标量
b = 2

# 扩展 a 的维度
c = np.expand_dims(a, axis=0)
print(c)
# 输出:
# [[1 2 3]]

# 进行广播操作
d = c + b
print(d)
# 输出:
# [[3 4 5]]

案例3:移除长度为1的维度

import numpy as np

# 创建一个数组
c = np.array([[[1, 2, 3]]])
print(c.shape)  # 输出: (1, 1, 3)

# 移除第 0 维
d = np.squeeze(c, axis=0)
print(d)
# 输出:
# [[1 2 3]]
print(d.shape)  # 输出: (1, 3)

# 移除第 1 维
e = np.squeeze(c, axis=1)
print(e)
# 输出:
# [[1 2 3]]
print(e.shape)  # 输出: (1, 3)

# 移除第 2 维
f = np.squeeze(c, axis=2)
print(f)
# 输出:
# ValueError: cannot select an axis to squeeze out which has size not equal to one
print(f.shape)

9.4 连接数组

函数名称参数说明
hstack(tup)tup:可以是元组,列表,或者numpy数组,返回结果为numpy的数组按水平顺序堆叠序列中数组(列方向)
vstack(tup)tup:可以是元组,列表,或者numpy数组,返回结果为numpy的数组按垂直方向堆叠序列中数组(行方向)

hstack函数要求堆叠的数组在垂直方向(行)上具有相同的形状。如果行数不一致,hstack() 将无法执行,并会抛出 ValueError 异常。

vstack() 要求堆叠的数组在水平方向(列)上具有相同的形状。如果列数不一致,将无法执行堆叠操作。

vstack() 和 hstack() 要求堆叠的数组在某些维度上具有相同的形状。如果维度不一致,将无法执行堆叠操作。

import numpy as np

# 创建两个形状不同的数组,行数一致
arr1 = np.array([[1, 2], [3, 4]])
arr2 = np.array([[5], [6]])
print(arr1.shape) 	# (2, 2)
print(arr2.shape)	# (2, 1)

# 使用 hstack 水平堆叠数组
result = np.hstack((arr1, arr2))
print(result)
# 输出:
# [[1 2 5]
#  [3 4 6]]

 

案例:

# 创建两个形状不同的数组,列数不一致
arr1 = np.array([[1, 2], [3, 4]])
arr2 = np.array([[5, 6, 7], [8, 9, 10]])

# 使用 vstack 垂直堆叠数组
result = np.vstack((arr1, arr2))

print(result)
# ValueError: all the input array dimensions except for the concatenation axis must match exactly
# 第一个数组在第1维有2个元素,而第二个数组在第1维有3个元素,因此无法直接连接。

 

9.5 分割数组

函数名称参数说明
hsplit(ary, indices_or_sections)ary:原数组 indices_or_sections:按列分割的索引位置将一个数组水平分割为多个子数组(按列)
vsplit(ary, indices_or_sections)ary:原数组 indices_or_sections:按行分割的索引位置将一个数组垂直分割为多个子数组(按行)
import numpy as np

'''
    hsplit 函数:
        1、将一个数组水平分割为多个子数组(按列)
        2、ary:原数组
        3、indices_or_sections:按列分割的索引位置
'''
# 创建一个二维数组
arr = np.array([[1, 2, 3, 4], [5, 6, 7, 8], [9, 10, 11, 12]])

# 使用 np.hsplit 将数组分割成三个子数组
# 分割点在索引1和3处,这意味着:
# 第一个子数组将包含从第0列到索引1(不包括索引1)的列,即第0列。
# 第二个子数组将包含从索引1(包括索引1)到索引3(不包括索引3)的列,即第1列到第2列。
# 第三个子数组将包含从索引3(包括索引3)到末尾的列,即第3列。
result = np.hsplit(arr, [1, 3])

# 查看结果
print("第一个子数组:\n", result[0])  # 输出包含第0列的子数组
print("第二个子数组:\n", result[1])  # 输出包含第1列和第2列的子数组
print("第三个子数组:\n", result[2])  # 输出包含第3列的子数组


'''
    vsplit 函数:
        1、将一个数组垂直分割为多个子数组(按行)
        2、ary:原数组
        3、indices_or_sections:按列分割的索引位置
'''
array_one = np.arange(12).reshape(2,6)
print('array_one 原数组:\n', array_one)
array_two = np.vsplit(array_one,[1])
print('vsplit 之后的数组:\n', array_two)

 

9.6 矩阵运算

np.dot

是一个通用的点积函数,适用于多种维度的数组。

  • 对于二维数组(矩阵),np.dot 等价于矩阵乘法。

  • 对于一维数组(向量),np.dot 计算的是向量的点积(内积)。

案例1:矩阵运算

import numpy as np

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

result = np.dot(a, b)
print(result)

 

案例2:向量点积

计算公式为:

$$
a\cdot b=a_{1}b_{1}+a_{2}b_{2}+⋯+a_{n}b_{n}
$$


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

result = np.dot(a, b)
print(result)

np.matmul

是专门用于矩阵乘法的函数,适用于二维及更高维度的数组。

案例:矩阵相乘

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

result = np.matmul(a, b)
print(result)

np.dot是通用点积函数,np.matmul专门用于矩阵运算,性能要好于np.dot

np.linalg.det

计算一个方阵(行数和列数相等的矩阵)的行列式。

案例:必须方阵才能计算

a = np.array([[1, 2], [3, 4]],dtype=int)
# 计算行列式
det_a = np.linalg.det(a)
print(det_a)

#输出:
-2.0000000000000004

结果不是-2,这是由于浮点数的二进制表示和计算过程中的舍入误差导致的。可以通过四舍五入来近似表示:

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值