1.Numpy的基础

1.1Numpy的概念

NumPy(Numerical Python)是一个用于科学计算的开源库,它为 Python 提供了支持大型多维数组和矩阵操作的功能,并包含了大量数学函数库,用于执行各种数值运算。

1.2Numpy的优点

Numpy包含了大量的数学函数,支持基本的算数运算,线性代数,矩阵等;

Numpy与其他的科学计算与数据分析库可以无缝兼容,例如Pandas、Matplotlib。用户可以方便地结合使用多个库进行数据处理和可视化。

NumPy 的广播机制允许对不同形状的数组进行算术运算,而无需显式地复制数据。这使得对数组进行元素级运算更加简洁和高效。

1.3Numpy的安装

用到代码:(-i 后的内容为清华镜像地址,下载速度会更快,比直接pip install numpy快很多)

pip install numpy==1.26.0 -i https://pypi.tuna.tsinghua.edu.cn/simple/

2.Ndarray

Numpy定义了一个n维数组对象,ndarray对象采用了数组的索引机制,将数组的每个元素投影到内存块上,并按照一定的布局进行排列,常见的布局方式有两种,按行排列(Row-major Order,C-style 数组的行是连续的)或按列排列(Column-major Order,Fortran-style 数组的列是连续的)

ndarray是通过array函数或者其他Numpy函数(zeros、ones、arange)创建的;array函数接受一个序列作为输入,并返回一个ndarray对象

2.1array创建对象

在使用array函数之前,我们需要导入numpy包,最好命名为np

import numpy as np

array的语法格式如下:

numpy.array(object, dtype = None, copy = True, order = None,ndmin = 0)

object:表示一个数组序列

dtype:可选参数,可以使用它改变数组的数据类型

copy:可选参数,表示数组是否可以被复制,默认是True

order:数组的内存布局(默认是C行排列)

ndmin:用于指定数组的维度

接下来我们来创建一个一维数组

array_one = np.array([1, 2, 3, 4], dtype=int, order= 'F', ndmin=1)
    print ("创建一个数组:",array_one)
    print ("创建一维数组:", type(array_one))
    print("ndim 查看、指定数组维度:",array_one.ndim)
    print(array_one.dtype)

结果如下:

创建一个数组: [1 2 3 4]
创建一维数组: <class 'numpy.ndarray'>
ndim 查看、指定数组维度: 1
int32

接下来创建一个二维数组

array_two = np.array([[1,1,1,1], [1,0,0,0]], dtype = float
                         , order= 'F')
    print("创建一个二维数组:\n", array_two)
    print("类型:", type(array_two))
    print(array_two.dtype)
    print("维度:", array_two.ndim)

结果如下:

创建一个二维数组:
 [[1. 1. 1. 1.]
 [1. 0. 0. 0.]]
类型: <class 'numpy.ndarray'>
float64
维度: 2

2.2指定/查看数组的维度

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

ndmin:用于指定数组的维度,创建数组时指定最小维度的参数,可以确保生成的数组至少是几维的。

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

arr = np.array([[1, 2, 3], [4, 5, 6], [7, 8, 9]])
print("数组形状:", arr.shape)
print("数组维度:", arr.ndim)

在这个例子中:

arr.shape 返回的数组形状(3, 3),表示3行3列

arr.ndim 返回的数组维度是2

2.3数组变维

可以通过直接设置shape属性来修改数组的维度

import numpy as np

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

# 修改数组形状为一维数组
arr.shape = (9,)
print("修改后的数组:", arr)
print("数组形状:", arr.shape)

结果如下:

修改后的数组:[1 2 3 4 5 6 7 8 9]
数组形状:(9,)

也可以使用reshape方法修改数组的维度

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

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

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

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

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

# 修改数组形状为 (1, 9)
arr_reshaped = arr.reshape((1, 9))
print("修改后的数组:", arr_reshaped)
print("数组形状:", arr_reshaped.shape)

结果如下:

修改后的数组:[[1 2 3 4 5 6 7 8 9]]
数组形状:(1, 9)

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

import numpy as np

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

# 使用 -1 作为占位符,重塑为 2 行
arr_reshaped = arr.reshape(2, -1)
print
[[1 2 3]
 [4 5 6]]

reshape() 还可以将一维数组重塑为三维数组:

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

# 使用 reshape() 函数将其转换为三维数组
reshaped_arr = arr.reshape((2, 3, 2))

print(reshaped_arr)
print("ndim:", reshaped_arr.ndim)
[[[ 1  2]
  [ 3  4]
  [ 5  6]]

 [[ 7  8]
  [ 9 10]
  [11 12]]]
ndim: 3

reshape((2, 3, 2))表示将数组重塑为一个三维数组,其形状为 (2, 3, 2),具体来说,这个形状表示:

  • 第一个维度:也叫做层维度,有 2 个元素。

  • 第二个维度:也叫做行维度,每个元素有 3 个元素。

  • 第三个维度:也叫做列维度,每个元素有 2 个元素。

  • 具体过程:

    首先,将一维数组分成 2 个部分:

    [1, 2, 3, 4, 5, 6] 和 [7, 8, 9, 10, 11, 12]

    然后,将每个部分分成 3 个部分:

    [1, 2], [3, 4], [5, 6] 和 [7, 8], [9, 10], [11, 12]

    最后,将每个部分分成 2 个部分,如:

    [1, 2]

    注意:形状 (2, 3, 2)中的参数个数相乘要等于数组中元素的个数,如:数组[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]有12个元素,形状(2,3,2)的参数相乘:2x3x2=12。

    3.数据类型

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

    序号

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

    arr = np.array([1, 2, 3])
    print(arr.dtype)  # 输出: int32

    3.可以使用 astype() 方法来转换数组中元素的数据类型。

    arr = np.array([1, 2, 3])
    arr_float = arr.astype(np.float64)
    print(arr_float.dtype)  # 输出: float64

    3.2 数据类型标识码

    NumPy 中每种数据类型都有一个唯一标识的字符码,int8, int16, int32, int64 四种数据类型可以使用字符串 'i1', 'i2','i4','i8' 代替,如下所示:

    字符 对应类型
    b 代表布尔型
    i 带符号整型
    u 无符号整型
    f 浮点型
    c 复数浮点型
    m 时间间隔(timedelta)
    M datatime(日期时间)
    O Python对象
    S,a 字节串(S)与字符串(a)
    U Unicode
    V 原始数据(void)

    整数类型

    数据类型 标识码 描述
    int8 i1 8 位有符号整数
    int16 i2 16 位有符号整数
    int32 i4 32 位有符号整数
    int64 i8 64 位有符号整数
    uint8 u1 8 位无符号整数
    uint16 u2 16 位无符号整数
    uint32 u4 32 位无符号整数
    uint64 u8 64 位无符号整数

    浮点数类型

    数据类型 标识码 描述
    float16 f2 16 位浮点数(半精度)
    float32 f4 32 位浮点数(单精度)
    float64 f8 64 位浮点数(双精度)

    复数类型

    数据类型 标识码 描述
    complex64 c8 64 位复数(单精度)
    complex128 c16 128 位复数(双精度)

    布尔类型

    数据类型 标识码 描述
    bool b1 布尔类型

    字符串类型

    数据类型 标识码 描述
    bytes S10 长度为 10 的字节串
    str U10 长度为 10 的 Unicode 字符串

    补充知识点:

    小端序(Little Endian),在小端序中,数据的低位字节存储在低地址处,高位字节存储在高地址处;大端序(Big Endian),在大端序中,数据的高位字节存储在低地址处,低位字节存储在高地址处。

    4.数组属性

    4.1 shape

    shape属性用于描述数组的维度,返回的是一个元组,包含数组每一维的大小;通过赋值可以调整数组维度的大小

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

    4.2 ndim

    ndim 属性功能:

    返回的是数组的维数

    4.3 itemsize

    itemsize 属性功能:用于描述数组中每个元素的大小(以字节为单位)。表示数组中每个元素所占用的内存空间。

    arr_int = np.array([1, 2, 3, 4, 5])
    print("整数数组的元素大小:", arr_int.itemsize)
    arr_float = np.array([1.0, 2.0, 3.0, 4.0, 5.0])
    print("浮点数组的元素大小:", arr_float.itemsize)

    结果如下:

    整数数组的元素大小: 8 
    浮点数组的元素大小: 8 

    4.4 flags

    flags 属性功能: 返回 ndarray 数组的内存信息

    import numpy as np
    arr = np.array([[1, 2, 3], [4, 5, 6]])
    print(arr.flags)
      C_CONTIGUOUS : True
      F_CONTIGUOUS : False
      OWNDATA : True
      WRITEABLE : True
      ALIGNED : True
      WRITEBACKIFCOPY : False
      UPDATEIFCOPY : False

    C_CONTIGUOUS:表示数组在内存中是 C 风格连续的(行优先)。
    如果为 True,则数组是 C 风格连续的。

    F_CONTIGUOUS:表示数组在内存中是 Fortran 风格连续的(列优先)。
    如果为 True,则数组是 Fortran 风格连续的。

    OWNDATA:如果数组拥有它所使用的内存(即数据不是来自视图或另一个数组的部分),则为 True。

    WRITEABLE:
    如果为 True,则数组是可写的;如果为 False,则数组是只读的。

    ALIGNED:
    表示数组是否对齐。如果为 True,则数组的数据在内存中是对齐的。

    WRITEBACKIFCOPY:如果数组是某个写时复制的视图,则为 True。数组是通过 np.copy 创建的副本,并且需要将更改写回原始数组。

    UPDATEIFCOPY:
    表示数组是否是通过 np.copy 创建的副本,并且需要将更改写回原始数组。
    如果为 True,则数组是通过 np.copy 创建的副本,并且需要将更改写回原始数组。

    #一维数组的内存信息,行优先和列优先都为True

    5.创建数组的其他方法

    5.1 empty()

    empty() 方法用来创建一个指定形状(shape)、数据类型(dtype)且未初始化的数组(数组元素为随机值)

    格式:

    numpy.empty(shape, dtype = float, order = 'C')

    shape:数组的形状,可以是整数或者整数元组

    dtype:数组的数据类型,默认为float

    order:C(行优先)和F(列优先)

    arr = np.empty((2, 3), dtype=float)
    print("未初始化的数组:\n", arr)

    结果类似于

    未初始化的数组:
     [[1.09576856e-311 1.86512319e-308 1.09575040e-311]
     [1.09575552e-311 2.27637712e-091 1.09576856e-311]]

    5.2 zeros()

    创建指定大小的数组,数组元素以 0 来填充

    格式

    numpy.zeros(shape, dtype = float, order = 'C')

    shape:数组的形状,可以是整数或者整数元组

    dtype:数组的数据类型,可选

    order:C(行优先)和F(列优先)

    import numpy as np
    arr = np.zeros((3,3),dtype=int)
    print(arr)
    [[0 0 0]
     [0 0 0]
     [0 0 0]]
    

    5.3 ones()

    创建指定形状的数组,数组元素以 1 来填充

    格式

    numpy.ones(shape, dtype = None, order = 'C')

    shape:数组的形状,可以是整数或者整数元组

    dtype:数组的数据类型,可选

    order:C(行优先)和F(列优先)

    arr = np.ones((3, 3),dtype=int,order='C')
    print(arr)
    [[1 1 1]
     [1 1 1]
     [1 1 1]]
    

    5.4 arange()

    numpy.arange函数用于创建一个等差数列的数组。它的功能类似于 Python 内置的 range() 函数,但返回的是一个 NumPy 数组而不是一个列表。

    格式:

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

    start:起始值,默认为0

    stop:终止值(不包含)

    step:步长,默认为1

    dtype:返回 ndarray 的数据类型,如果没有提供,则会使用输入数据的类型

    arr0 = np.arange(0, 10, )
    print(arr0)
    arr1 = np.arange(1, 11, 3)
    print(arr1)
    [0 1 2 3 4 5 6 7 8 9]
    [ 1  4  7 10]

    5.5 linspace

    函数用于创建一个指定范围内的等间隔数值序列数组。它与numpy.arange类似,但允许用户直接指定生成元素的数量,而不是步长。这在生成特定数量的数值时非常有用。

    格式:

    np.linspace(start, stop, num=50, endpoint=True, retstep=False, dtype=None)

    start:起始值,默认为0

    stop:终止值(不包含)

    num:表示要生成多少个均匀的样本量,默认为50

    endpoint:默认为True,表示包含终止值,反之不包含

    retstep:表示是否返回步长,如果为 True,则返回一个包含数组和步长的元组;如果为 False,则只返回数组。默认为 False

    dtype:返回 ndarray 的数据类型,如果没有提供,则会使用输入数据的类型

    arr, step = np.linspace(0, 10, 20, endpoint=False, retstep=True)
    print(step, arr)
    0.5 [0.  0.5 1.  1.5 2.  2.5 3.  3.5 4.  4.5 5.  5.5 6.  6.5 7.  7.5 8.  8.5
     9.  9.5]
    

    5.6 full()

    full()用于创建一个填充指定值的数组。

    格式:

    numpy.full(shape, fill_value, dtype=None, order='C')

    shape:数组的形状,可以是整数或者整数元组

    fill_value:填充的值

    dtype:数组的数据类型,可选

    order:C(行优先)和F(列优先)

    arr = np.full((3, 3), 4)
    print(arr)
    [[4 4 4]
     [4 4 4]
     [4 4 4]]
    

    5.7 logspace()

    函数用于在对数刻度上生成等间隔的数值序列。它特别适用于生成对数刻度上的数据点,例如用于绘制对数图。以下是lecapsgo函数的详细说明和示例:

    格式:

    numpy.logspace(start, stop, num=50, endpoint=True, base=10.0, dtype=None, axis=0)

    start:起始值,默认为0

    stop:终止值(不包含)

    num:表示要生成多少个均匀的样本量,默认为50

    endpoint:默认为True,表示包含终止值,反之不包含

    base:对数的底数,默认为10

    dtype:数组数据类型

    axis:沿着指定的轴放置结果,默认为0

    arr = np.logspace(1, 3, 4, base=2)
    print(arr)
    [ 2.  4.  8. 16.]

    6.切片slice()

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

    slice 操作也可通过 [start:stop:step] 的形式来实现

    start:起始值,默认为0

    stop:终止值(不包含)

    step:步长,选取元素的间隔

    import numpy as np
    def np_slice():
        arr = np.array([[1, 2, 3], [4, 5, 6], [7, 8, 9]])
        print(arr)
        print('_______________')
        #按照行切片
        arr1 = arr[0:2]
        print(arr1)
        #按照列切片
        arr2 = arr[::, 0:2]
        print(arr2)
        #行列都切片
        arr3 = arr[0:2, 0:2]
        print(arr3)
        #'...'切片是保留所有行或者所有列
        """arr4 = arr[0:2, ...]
        print(arr4)"""
        #可变的数据类型,切片得到的新数组是原数组的浅拷贝(,或者是视图),修改视图中的数据会影响原数组
        arr1[0][0] = 100
        print(arr1)
        print(arr)
    
    if __name__=='__main__':
        np_slice()
    [[1 2 3]
     [4 5 6]
     [7 8 9]]
    _______________
    [[1 2 3]
     [4 5 6]]
    [[1 2]
     [4 5]
     [7 8]]
    [[1 2]
     [4 5]]
    [[100   2   3]
     [  4   5   6]]
    [[100   2   3]
     [  4   5   6]
     [  7   8   9]]

    冒号 : 的作用

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

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

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

  • 省略号 (...) 的作用

    省略号用于在切片中表示多个冒号,用于省略不想显式书写的维度。

    7.高级索引

    NumPy的高级索引功能非常强大,允许你用多种方式选择和操作数组中的元素。相比于基本索引,高级索引可以访问到数组中的任意元素,并且可以用来对数组进行复杂的操作和修改。

    7.1整数数组索引

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

    这是一维数组的高级索引方式

    arr = np.array([10, 20, 30, 40, 50])
    index_arr = np.array([0, 2, 4])
    print(arr[index_arr])  
    # 输出: [10 30 50]

     这是多维数组的高级索引方式;[0,1,2]代表行索引、[1,0,1]代表列索引;即取出索引坐标 (0,0)、(1,1)、(0,2) 的元素

    arr = np.array([[1, 2], [3, 4], [5, 6]])
    rows = np.array([0, 1, 2])
    cols = np.array([1, 0, 1])
    print(arr[rows, cols])  
    # 输出: [2 3 6]

    7.2布尔索引

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

    arr = np.array([1, 2, 3, 4, 5, 6, 7, 8, 9])
    bool_idx = arr > 5
    print(bool_idx) 
    # 输出: [False False False False False  True  True  True  True  True]
    print(arr[bool_idx])
    # 输出: [ 6  7  8  9]
    

    多维数组的布尔索引

    arr = np.array([[1, 2, 3], [4, 5, 6], [7, 8, 9]])
    bool_idx = arr > 5
    print(bool_idx)
    # 输出:
    # [[False False False]
    #  [False False  True]
    #  [ True  True  True]]
    
    print(arr[bool_idx]) 
    # 输出: [6 7 8 9]

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

    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]
    
    # 使用布尔索引获取满足条件的元素
    print(arr[bool_idx]) 
    # 输出: [6 7 8]

     7.3 高级索引补充

    test01():
        data = np.arange(1,13).reshape(3,4)
        #行级别的数组整数索引列表
        #通过广播机制将行索引数组和列索引数组转换为相同的形状,然后在按照数组的整数索引获取对应的元素。
    
        print(data[[[1],[2]],[0,1,2]])
    
    #输出
    [[ 5  6  7]
     [ 9 10 11]]
    

    8.广播(*)

    广播(Broadcasting)是一种强大的机制,它允许不同形状的数组进行算术运算,这种机制的核心是对形状较小的数组,在横向或纵向上进行一定次数的重复,使其与形状较大的数组拥有相同的维度。广播使得NumPy在处理数组时更加灵活和高效。

    广播规则

    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]]
    # 两个数组中最大行和最大列
        a = np.array([[1], [2]])
        b = np.array([100, 200, 300])
        c = a + b
        print(c)
    #输出:
    [[101 201 301]
     [102 202 302]]

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

    a = np.arange(1,5)
        b = np.arange(1,5).reshape(1,4).T
        # a 的形状为(4,1),被广播为(4,4)
        # b 的形状为(1,4),被广播为(4,4)
        # 形状相同后进行对应元素的运算
        c = a + b
        print(c)
    #输出:
    
    [[2 3 4 5]
     [3 4 5 6]
     [4 5 6 7]
     [5 6 7 8]]

    3.不匹配:如果两个数组在某个维度上的长度既不相同也不为 1,则广播失败,抛出 ValueError。

    9.遍历数组

    9.1遍历数组的第一维度

    arr = np.array([[1,2,3],[4,5,6]])
    #只遍历数组中的第一维元素
    for i in arr:
        print(i)
      
    #输出:
    [1 2 3]
    [4 5 6]
    

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

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

    9.2 nditer逐个访问元素

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

    参数

    order:C(行优先)和F(列优先)

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

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

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

    op_flags:用于指定操作数的行为。

            readonly: 只读操作数。

            readwrite: 读写操作数。

            writeonly: 只写操作数。

        arr = np.arange(1,7).reshape(2,3)
        iter = np.nditer(arr, flags=['multi_index'])
        for i in iter:
            print(i , iter.multi_index)
    
        iter1 = np.nditer(arr, flags=['external_loop'])
        for i in iter1:
            print(i)
    
        iter2 = np.nditer(arr, flags=['external_loop'], order='F')
        for i in iter2:
            print(i)
    
    #输出:
    1 (0, 0)
    2 (0, 1)
    3 (0, 2)
    4 (1, 0)
    5 (1, 1)
    6 (1, 2)
    [1 2 3 4 5 6]
    [1 4]
    [2 5]
    [3 6]
    
    arr = np.arange(1, 7).reshape(2, 3)
    for x in np.nditer(arr, op_flags=['readwrite']):
        x[...] = x * 2
    print(x)
    #输出:
    2
    4
    6
    8
    10
    12

    9.3 X[…]

    是 NumPy 中的一种索引方式,表示获取数组 x 的一个视图,对数组 x 进行原地修改,而不是创建一个新的数组。 返回一个可写视图(writable view),允许直接修改原数组中的元素。

    注意:当你使用 x[…] 时,x 必须是一个数组或数组的视图,而不是一个标量。

    arr = np.array([[1, 2, 3], [4, 5, 6]])
    # 使用读写操作数遍历数组
    # x[...] = x * 2 将数组 arr 中的每个元素乘以 2,并写回到原数组中。
    # x实际返回一个包含当前元素的数组,而不是标量,所以可以使用x[...]
    for x in np.nditer(arr, op_flags=['readwrite']):
        x[...] = 2 * x
    
    print(arr)
    # 输出:
    # [[ 2  4  6]
    #  [ 8 10 12]]
    

    10.数组操作

    10.1数组变维

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

    10.1.1 flat

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

    格式:

    ndarray.flat
    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=" ")
    
    #输出
    原数组元素:
    [0 1] [2 3] 
    使用flat属性,遍历数组:
    0 1 2 3 
    进程已结束,退出代码为 0
    
    

    10.1.2 flatten()

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

    格式:

    ndarray.flatten(order='C')

    案例:

    arr = np.array([[1, 2, 3], [4, 5, 6]])
    
    # 使用 flatten 方法按行优先顺序展开
    flat_arr = arr.flatten(order='C')
    
    print(flat_arr)
    # 输出:
    # [1 2 3 4 5 6]

    order:如果是'A'的话,按照元素在内存中的顺序展开

    10.1.3 ravel()

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

    格式:

    ndarray.ravel()
    arr = np.array([[1, 2, 3], [4, 5, 6]])
    
    # 使用 ravel 方法按行优先顺序展开
    ravel_arr = arr.ravel()
    
    print(ravel_arr)
    # 输出:
    # [1 2 3 4 5 6]
    
    ravel_arr[-1] = 7
    print(arr)
    # 输出:
    # [[1 2 3]
    #  [4 5 7]]

    10.2数组转置

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

     案例:

    import numpy as np
    def test01():
        #transpose():数组装置,返回原数组的视图
        #T属性:数组装置,返回的原数组的视图
        arr = np.arange(1,13).reshape(-1,4)
        arr1 = arr.T
        print(arr1)
        arr1[1][1] = 100
        print(arr)
        print('_________________________________________________________________model')
        arr2 = arr.transpose()
        print(arr2)
        arr2[1][1] = 50
        print(arr)
    
    if __name__=='__main__':
        test01()
    
    #输出:
    [[ 1  5  9]
     [ 2  6 10]
     [ 3  7 11]
     [ 4  8 12]]
    [[  1   2   3   4]
     [  5 100   7   8]
     [  9  10  11  12]]
    _________________________________________________________________model
    [[  1   5   9]
     [  2 100  10]
     [  3   7  11]
     [  4   8  12]]
    [[ 1  2  3  4]
     [ 5 50  7  8]
     [ 9 10 11 12]]

     10.3修改数组维度

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

    函数名称 参数 说明
    expand_dims(arr, axis) arr:输入数组 axis:新轴插入的位置 在指定位置插入新的轴(相对于结果数组而言),从而扩展数组的维度
    squeeze(arr, axis) arr:输入数的组 axis:取值为整数或整数元组,用于指定需要删除的维度所在轴,指定的维度值必须为 1 ,否则将会报错,若为 None,则删除数组维度中所有为 1 的项 删除数组中维度为 1 的项
        arr = np.array([1,2,3,4])
        arr1 = np.expand_dims(arr, axis=0)
        arr2 = np.expand_dims(arr, axis=1)
        print(arr1)
        print(arr2)
    
    
    #输出:
    [[1 2 3 4]]
    [[1]
     [2]
     [3]
     [4]]
    #np.squeeze():数组降维,如果指定axis,则按照axis删除维度,前提:该纬度值必须唯一,否则异常
    #如果不指定axis, 则自动判断维度是否为1,并删除维度为1的维度
        arr = np.array([[[1,2,3]]])
        print(arr.shape)
        arr1 = np.squeeze(arr, axis=0)
        print(arr1)
        arr2 = np.squeeze(arr, axis=1)
        print(arr2)
        arr3 = np.squeeze(arr)
        print(arr3)
    
    #输出:
    (1, 1, 3)
    [[1 2 3]]
    [[1 2 3]]
    [1 2 3]

    增加数组维度的操作类似:

    test03():
        arr = np.array([1,2,3])
        #newaxis:在数组的指定位置添加一个维度,可以在行或列添加维度
        arr1 = arr[np.newaxis,:]
        arr2 = arr[:, np.newaxis]
        print(arr1)
        print(arr2)
    
    #输出:
    [[1 2 3]]
    [[1]
     [2]
     [3]]

    10.4数组拼接

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

    hstack:如果行维度不一致,将无法执行堆叠操作。

    test01():
        a = np.array([[1,2,3],[4,5,6]])
        b = np.array([[1,1],[2,2]])
        #b = np.array([[7,8],[1,2],[3,4]])
        #hstack:水平方向(按列)拼接数组, 前提:数组行数一致
        print(a.shape, b.shape)
        c = np.hstack((a, b))
        print(c)
    
    #输出:
    (2, 3) (2, 2)
    [[1 2 3 1 1]
     [4 5 6 2 2]]
    

    vstack:如果列维度不一致,将无法执行堆叠操作。

    test02():
        a = np.array([[1,2],[3,4],[5,6]])
        b = np.array([[7,8],[9,10]])
        #vstack:垂直方向(按行)拼接数组, 前提:数组列数一致
        c = np.vstack((a,b))
        print(c)
    
    #输出:
    [[ 1  2]
     [ 3  4]
     [ 5  6]
     [ 7  8]
     [ 9 10]]

    10.5切割数组

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

    hsplit:

    test01():
        arr = np.arange(1,13).reshape(-1,4)
        print(arr)
        #hsplit(arr):按照水平方向切割数组,按列切割
        #ary:要切割的数组
        #indecies_or_sections:表示要切割的索引下标(不包含下标值)
        resutl = np.hsplit(arr,[1, 3])
        print(resutl[0])
        print(resutl[1])
        print(resutl[2])
    
    #输出:
    [[ 1  2  3  4]
     [ 5  6  7  8]
     [ 9 10 11 12]]
    [[1]
     [5]
     [9]]
    [[ 2  3]
     [ 6  7]
     [10 11]]
    [[ 4]
     [ 8]
     [12]]
    

    vsplit:

    test02():
        arr = np.arange(1,13).reshape(-1,3)
        # vsplit(arr):按照垂直方向切割数组,按行切割
        # ary:要切割的数组
        # indecies_or_sections:表示要切割的索引下标(不包含下标值)
        print(arr)
        result = np.vsplit(arr, [2])
        print(result[0])
        print(result[1])
    
    #输出:
    [[ 1  2  3]
     [ 4  5  6]
     [ 7  8  9]
     [10 11 12]]
    [[1 2 3]
     [4 5 6]]
    [[ 7  8  9]
     [10 11 12]]

    10.6矩阵运算

    np.dot

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

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

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

    test01():
        a = np.arange(1,5)
        b = np.arange(5,9)
        #np.dot:当数组是一维数组时,该方法是点积运算;
        # 当数组是二维数组时,该方法是矩阵乘法
        print(np.dot(a,b))
    
    #输出:70
    test02():
        a = np.arange(1,5).reshape(2,2)
        b = np.arange(5,9).reshape(2,2)
        print(np.dot(a,b))
    #输出:
    [[19 22]
     [43 50]]
    

    np.linalg.det

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

    test03():
        a = np.array([[1,2,3],[3,4,3],[1,2,1]])
        det = np.linalg.det(a)
        print(det)
    #输出:
    4.000000000000001

    结果不是4,这是由于浮点数的二进制表示和计算过程中的舍入误差导致的。

    np.matmul

    是专门用于矩阵乘法的函数,适用于二维及更高维度的数组。用法和np.dot类似

    11.数组元素的增删查改

    11.1 resize

    函数名称 参数 说明
    resize(a, new_shape) a:操作的数组 new_shape:返回的数组的形状,如果元素数量不够,重复数组元素来填充新的形状 返回指定形状的新数组
    test01():
        a = np.arange(1,7).reshape(2,3)
        b = np.resize(a, (3, 3))
        # np.resize(array, new_shape):数组修改形状,如果原数组的元素不够,则重新遍历原数组的元素不够,
        #和reshape()的区别,reshape要求新数组和原数组的元素总数相同,resize方法不受约束。
        print(b)
    
    #输出:
    [[1 2 3]
     [4 5 6]
     [1 2 3]]

    11.2 append

    函数名称 参数 说明
    append(arr, values, axis=None) arr:输入的数组 values:向 arr 数组中添加的值,需要和 arr 数组的形状保持一致 axis:默认为 None,返回的是一维数组;当 axis =0 时,追加的值会被添加到行,而列数保持不变,若 axis=1 则与其恰好相反 在数组的末尾添加值,返回一个一维数组
    test02():
        a = np.arange(1,7).reshape(2,3)
        # axis为None, 返回的是一个一维数组,添加的值在数组尾部
        b = np.append(a, [7,8,9])
        print(b)
        # axis为0,按行添加数值到数组尾部
        #注意,values数组维度数要和原来的维度数一致,
        # 在添加行时,values的列数要和原数组一致,否则报异常
        c = np.append(a, [[7,8,9]], axis=0)
        print(c)
        # axis为1,按列添加数值到数组尾部
        #注意,values数组维度数要和原来的维度数保持一致,
        # 在添加列时,values的行数要和原来的一致
        d = np.append(a,[[7,9], [8,10]], axis=1)
        print(d)
    
    #输出:
    [1 2 3 4 5 6 7 8 9]
    [[1 2 3]
     [4 5 6]
     [7 8 9]]
    [[ 1  2  3  7  9]
     [ 4  5  6  8 10]]

    11.3 insert

    函数名称 参数 说明
    insert(arr, obj, values, axis) arr:输入的数组 obj:表示索引值,在该索引值之前插入 values 值 values:要插入的值 axis:默认为 None,返回的是一维数组;当 axis =0 时,追加的值会被添加到行,而列数保持不变,若 axis=1 则与其恰好相反 沿规定的轴将元素值插入到指定的元素前
    test03():
        # insert 方法:在原数组指定的索引前面插入元素
        #注意:axis为None,返回一维数组;axis=0,行插入;axis=1, 列插入
        a = np.arange(1,7).reshape(2,3)
        b = np.insert(a,[2],100,axis=0)
        print(b)
    
    #输出:
    [[  1   2   3]
     [  4   5   6]
     [100 100 100]]

    如果obj为-1,表示插入在倒数第一个元素之前,不是在最后一列

    11.4 delete

    函数名称 参数 说明
    delete(arr, obj, axis) arr:输入的数组 obj:表示索引值,要删除数据的索引 axis:默认为 None,返回的是一维数组;当 axis =0 时,删除指定的行,若 axis=1 则与其恰好相反 删掉某个轴上的子数组,并返回删除后的新数组
    test04():
        #np.delete(arr,obj,axis):按照指定的object(索引)删除对应的元素
        # axis为None,返回一维数组,删除对应索引的元素;
        # axis=0,按行删除;axis=1,按列删除
        a = np.arange(1,7).reshape(2,3)
        b = np.delete(a,[0],0)
        print(b)
    
    #输出:
    [[4 5 6]]

    11.5 argwhere

    返回数组中非 0 元素的索引,若是多维数组则返回行、列索引组成的索引坐标

    test05():
        a = np.arange(6).reshape(2,3)
        #np.argwhere(arr):返回数组中非零元素对应的索引下标
        #也可以通过布尔索引获取满足布尔条件的索引下标
        print(np.argwhere(a))
        print(np.argwhere(a>4))
    
    #输出:
    [[0 1]
     [0 2]
     [1 0]
     [1 1]
     [1 2]]
    [[1 2]]
  • where:
    语法:np.where(condition, x, y)
    功能:根据条件返回对应元素。如果满足条件,则返回 x 否则返回 y。
    返回值:一个与输入数组形状相同的数组。

  • argwhere:
    语法:np.argwhere(condition)
    功能:返回满足条件的元素的索引。
    返回值:一个二维数组,每一行表示满足条件的元素的索引。

  • 11.6 unique

    函数名称 参数 说明
    unique(ar, return_index=False, return_inverse=False, return_counts=False, axis=None) ar:输入的数组 return_index:如果为 True,则返回新数组元素在原数组中的位置(索引) return_inverse:如果为 True,则返回原数组元素在新数组中的位置(逆索引) return_counts:如果为 True,则返回去重后的数组元素在原数组中出现的次数 删掉某个轴上的子数组,并返回删除后的新数组
    test06():
        a = np.array([1, 2, 2, 3, 4, 4, 5])
        # np.unique():数组元素去重
        #return_index:如果为Ture,返回新数组元素在原数组中索引位置
        #return_inverse:如果为Ture,返回原数组元素在新数组元素中索引位置
        #return_counts:如果为True,返回元素在数组中的出现次数
        b, idx = np.unique(a, return_index = True)
        arr = np.array([1, 2, 2, 5, 5, 5, 4, 4, 4, 4])
        b2, idx2 = np.unique(arr,return_inverse=True)
        c, count = np.unique(a,return_counts=True)
        print(b2)
        print(idx2)
        print(count)
    
    #输出:
    [1 2 4 5]
    [0 1 1 3 3 3 2 2 2 2]
    [1 2 1 2 1]
    

    12.统计函数

    12.1amin()和amax()

            计算数组沿指定轴的最小值与最大值,并以数组形式返回

            对于二维数组来说,axis=1 表示沿着水平方向,axis=0 表示沿着垂直方向

    test01():
        a = np.array([[1,2,3],[4,5,6]])
        # amax():求数组最大值
        # amin():求数组最小值
    
        # axis=none,求整个数组最大值或最小值
        # axis=0,按列求最大值或最小值
        # axis=1,按行求最大值或最小值
        print(np.amax(a, axis=0))
        print(np.amin(a, axis=0))
    
        print(np.amax(a, axis=1))
        print(np.amin(a, axis=1))
    
        print(np.amax(a))
        print(np.amin(a))
    
    #输出:
    [4 5 6]
    [1 2 3]
    [3 6]
    [1 4]
    6
    1

    12.2 ptp()

            计算数组元素中最值之差值,即最大值 – 最小值

            对于二维数组来说,axis=1 表示沿着水平方向,axis=0 表示沿着垂直方向

    a = np.arange(1,7).reshape(2,3)
        #  np.ptp():amax() - amin().最大值减去最小值
        # axis=none,求整个数组最大值或最小值
        # axis=0,按列求最大值或最小值
        # axis=1,按行求最大值或最小值
        print(np.ptp(a))
        print(np.ptp(a, axis=1))
    
    #输出:
    5
    [2 2]

    12.3 median()

    用于计算中位数,中位数是指将数组中的数据按从小到大的顺序排列后,位于中间位置的值。如果数组的长度是偶数,则中位数是中间两个数的平均值。

    a = np.arange(1,7).reshape(-1,3)
        #np.madian():求数组的中位数
        # axis=none,求整个数组中位数
        # axis=0,按列求中位数
        # axis=1,按行求中位数
    print(np.median(a, axis=0))
    print(np.median(a, axis=1))
    
    #输出:
    [2.5 3.5 4.5]
    [2. 5.]
    

    12.4mean()

    沿指定的轴,计算数组中元素的算术平均值(即元素之总和除以元素数量)

    test04():
        a = np.array([[1,2,3],[4,5,6]])
        print(np.mean(a))
        print(np.mean(a, axis=0))
        print(np.mean(a, axis=1))
    
    #输出:
    3.5
    [2.5 3.5 4.5]
    [2. 5.]

    12.5 average()

    加权平均值是将数组中各数值乘以相应的权数,然后再对权重值求总和,最后以权重的总和除以总的单位数(即因子个数);根据在数组中给出的权重,计算数组元素的加权平均值。该函数可以接受一个轴参数 axis,如果未指定,则数组被展开为一维数组。

    $$ 加权平均值=\dfrac{∑_{i=1}^n(x_i⋅w_i)}{∑_{i=1}^nw_i} $$

    其中 xi是数组中的元素,wi是对应的权重。

    如果所有元素的权重之和等于1,则表示为数学中的期望值。

    a = np.array([1,2,3,4,5])
    w = np.array([0.1,0.2,0.3,0.2,0.2])
    #np.average():计算数组的加权平均值:所有元素值乘以对应的权重相加,除以所有权重之和
    print(np.average(a, weights=w))
    
    #输出:
    3.2

    12.6 var()和std()

    在 NumPy 中,计算方差时使用的是统计学中的方差公式,而不是概率论中的方差公式,主要是因为 NumPy 的设计目标是处理实际数据集,而不是概率分布。

    np.var 函数默认计算的是总体方差(Population Variance),而不是样本方差(Sample Variance)。

    总体方差:

    对于一个总体数据集 X={x1,x2,…,xN},总体方差的计算公式为:
    $$
    σ^2=\dfrac{1}{N}∑_{i=1}^N(x_i−μ)^2
    $$
    其中:

    – N是总体数据点的总数。
    – μ是总体的均值。

    标准差是方差的算术平方根,用来描述一组数据平均值的分散程度。若一组数据的标准差较大,说明大部分的数值和其平均值之间差异较大;若标准差较小,则代表这组数值比较接近平均值

    test06():
        a = np.arange(1,6)
        #np.var():计算数组元素的方差
        #参数:ddof:默认使用总体方差,如果设置为1,使用样本方差
        print(np.var(a,ddof=1))
        #np.std():计算标准差
        print(np.std(a,ddof=0))
    
    #输出:
    2.5
    1.4142135623730951

    作者:inquisitor.dom

    物联沃分享整理
    物联沃-IOTWORD物联网 » Python中Numpy库的学习

    发表回复