美文网首页
深入学习NumPy:掌握数组操作与应用的终极指南

深入学习NumPy:掌握数组操作与应用的终极指南

作者: 温柔倾怀 | 来源:发表于2023-06-01 15:18 被阅读0次

    1. NumPy简介

    NumPy是Python中一个重要的库,用于科学计算和数据分析。它提供了一个强大的多维数组对象(ndarray)和用于操作这些数组的函数。NumPy是许多其他Python科学计算库的基础,如Pandas、SciPy和Matplotlib。

    NumPy的背景和目标

    NumPy最初由Travis Olliphant于2005年创建,并且它是Numeric和Numarray两个库的继承者。NumPy的目标是为Python提供一种高效的数组处理方法,使得科学计算更加便捷和高效。

    NumPy的主要特征和应用场景

    NumPy的主要特征包括:

    • 强大的多维数组对象:NumPy的核心是ndarray对象,它可以存储任意维度的同类型数据。这种数组对象非常适合进行数值计算和数据处理。
    • 快速的数值运算:NumPy通过对数组的操作使用高效的C语言代码实现,因此在数值运算方面比纯Python代码更快速。
    • 广播机制:NumPy引入了广播机制,使得不同形状的数组可以进行运算,这样可以简化代码并提高运算效率。
    • 丰富的数学函数库:NumPy提供了大量的数学函数和线性代数操作,如三角函数、指数函数、统计函数、矩阵分解等,满足科学计算的需求。
    • 与其他科学计算库的兼容性:NumPy与其他常用的科学计算库(如SciPy、Pandas、Matplotlib)紧密结合,可以方便地与这些库一起使用。

    NumPy在以下应用场景中得到广泛应用:

    • 数据分析和处理:NumPy的数组对象提供了高效的数据结构和操作,使得数据分析和处理变得更加便捷。它可以处理大量数据并进行快速的数值计算。
    • 科学计算:NumPy提供了丰富的数学函数和线性代数操作,适用于科学计算中的各种任务,如信号处理、图像处理、统计分析等。
    • 机器学习和人工智能:NumPy是许多机器学习和深度学习框架的基础。它提供了高效的数组操作和数学函数,可以加速算法的实现和运行。

    NumPy与Python的关系

    NumPy是用Python编写的,是Python科学计算生态系统中的核心组件之一。NumPy提供了高性能的数组对象和数组操作函数,使得Python在科学计算领域有了更强大的能力。

    NumPy通过底层的C语言代码实现了数组操作的高效性,并通过Python的接口与用户进行交互。这使得NumPy既具有高性能的计算能力,又保持了Python的简洁和易用性。

    NumPy还与Python的标准库和其他科学计算库紧密结合,使得用户可以方便地进行数据的读写、可视化和分析。通过NumPy,Python成为了一种强大的科学计算语言,受到了广泛的应用和开发者的喜爱。

    2. NumPy数组

    NumPy的核心是多维数组对象ndarray,它提供了一种高效存储和操作大量数据的方式。在本节中,我们将学习如何创建NumPy数组,了解数组的属性和方法,并掌握基本的数组操作。

    创建NumPy数组

    NumPy数组可以通过多种方式创建,如以下示例所示:

    通过Python列表创建数组

    import numpy as np
    
    # 创建一维数组
    arr1 = np.array([1, 2, 3, 4, 5])
    print(arr1)
    # [1 2 3 4 5]
    
    # 创建二维数组
    arr2 = np.array([[1, 2, 3], [4, 5, 6]])
    print(arr2)
    # [[1 2 3] 
    #  [4 5 6]]
    

    使用NumPy函数创建特殊数组

    # 创建全零数组
    zeros = np.zeros((2, 3))
    print(zeros)
    # [[0. 0. 0.] 
    #  [0. 0. 0.]]
    
    # 创建全一数组
    ones = np.ones((3, 2))
    print(ones)
    # [[1. 1.]   
    #  [1. 1.]   
    #  [1. 1.]] 
    
    # 创建指定范围的等间隔数组
    range_arr = np.arange(0, 10, 2)
    print(range_arr)
    # [0 2 4 6 8]
    
    # 创建指定大小的随机数组
    random_arr = np.random.rand(2, 3)
    print(random_arr)
    # [[0.98409252 0.27752055 0.89984634]
    #  [0.00264179 0.62695002 0.77690454]]
    

    数组的属性和方法

    NumPy数组具有许多有用的属性和方法,可以帮助我们了解和操作数组。以下是一些常用的属性和方法:

    数组的形状和维度

    arr = np.array([[1, 2, 3], [4, 5, 6]])
    print(arr.shape)   # 输出数组的形状
    # (2, 3)
    print(arr.ndim)    # 输出数组的维度
    # 2
    

    数组的数据类型

    arr = np.array([1, 2, 3])
    print(arr.dtype)   # 输出数组的数据类型
    # int32
    

    数组的大小和元素个数

    arr = np.array([[1, 2, 3], [4, 5, 6]])
    print(arr.size)    # 输出数组的大小,即元素的总个数
    # 6
    print(arr.itemsize)    # 输出数组中每个元素的字节大小
    # 4
    

    操作数组的基本操作

    数组的索引和切片

    arr = np.array([1, 2, 3, 4, 5])
    print(arr[0])     # 输出第一个元素
    # 1
    print(arr[2:4])   # 输出索引为2和3的元素
    # [3 4]
    
    arr = np.array([[1, 2, 3], [4, 5, 6]])
    print(arr[1, 2])  # 输出第二行第三列的元素
    # 6
    print(arr[:, 1])  # 输出所有行的第二列元素
    # [2 5]
    

    数组的变形

    arr = np.array([1, 2, 3, 4, 5, 6])
    # [1 2 3 4 5 6]
    reshaped_arr = arr.reshape(2, 3)   # 将一维数组变形为二维数组
    print(reshaped_arr)
    # [[1 2 3]
    #  [4 5 6]]
    
    arr = np.array([[1, 2], [3, 4]])
    # [[1 2]
    #  [3 4]]
    flattened_arr = arr.flatten()   # 将二维数组展平为一维数组
    print(flattened_arr)
    # [1 2 3 4]
    

    数组的拼接

    arr1 = np.array([1, 2, 3])
    # [1 2 3]
    arr2 = np.array([4, 5, 6])
    # [4 5 6]
    concatenated_arr = np.concatenate((arr1, arr2))   # 拼接两个数组
    print(concatenated_arr)
    # [1 2 3 4 5 6]
    
    arr1 = np.array([[1, 2], [3, 4]])
    # [[1 2]
    #  [3 4]]
    arr2 = np.array([[5, 6]])
    # [[5 6]]
    concatenated_arr = np.concatenate((arr1, arr2), axis=0)   # 沿行方向拼接
    print(concatenated_arr)
    # [[1 2]
    #  [3 4]
    #  [5 6]]
    

    3. NumPy数据类型

    NumPy提供了多种数据类型来存储和处理数组中的元素。在本节中,我们将学习常见的数据类型、数据类型转换以及如何自定义数据类型。

    常见的数据类型

    NumPy支持以下常见的数据类型:

    • bool:布尔值(True或False)
    • int:整数类型,根据平台可能是int32或int64
    • float:浮点数类型,根据平台可能是float32或float64
    • complex:复数类型,由两个浮点数表示实部和虚部
    • str:字符串类型
    • object:Python对象类型
    • datetime:日期时间类型
    • timedelta:时间间隔类型
    • np.void:Void类型,可以存储任意类型的数据

    数据类型转换

    在NumPy中,可以使用astype()函数进行数据类型转换。以下是一些常见的数据类型转换示例:

    arr = np.array([1, 2, 3])
    # [1 2 3]
    
    # 转换为浮点数类型
    float_arr = arr.astype(float)
    print(float_arr)
    # [1. 2. 3.]
    
    # 转换为字符串类型
    str_arr = arr.astype(str)
    print(str_arr)
    # ['1' '2' '3']
    
    # 转换为布尔类型
    bool_arr = arr.astype(bool)
    print(bool_arr)
    # [ True  True  True]
    

    自定义数据类型

    NumPy还允许用户自定义数据类型,以满足特定的需求。可以使用np.dtype()函数来定义自定义数据类型,并指定字段的名称和数据类型。以下是一个自定义数据类型的示例:

    • 对于定义的自定义数据类型,其中的字符串字段需要指定字符串的最大长度
    • 未指定字符串字段的最大长度,则默认为长度为0的空字符串,导致相关字段为空
    • 'U10'表示最大长度为10的Unicode字符串
    # 定义自定义数据类型
    person_dtype = np.dtype([('name', 'U10'), ('age', 'int'), ('height', 'float')])
    
    # 创建一个数组并使用自定义数据类型
    person_arr = np.array([('John', 25, 180.5), ('Alice', 30, 165.2)], dtype=person_dtype)
    print(person_arr)
    # [('John', 25, 180.5) ('Alice', 30, 165.2)]
    print(person_arr[0]['name'])
    # John
    

    4. 数组计算

    NumPy提供了丰富的数组计算方法、广播机制以及数学函数和线性代数操作,使得处理和操作数组变得更加便捷和高效。

    数组的计算方法

    使用NumPy,你可以对数组进行各种数学运算和统计计算。以下是一些常用的数组计算方法示例:

    • np.sum(arr):计算数组所有元素的总和。
    • np.mean(arr):计算数组所有元素的平均值。
    • np.std(arr):计算数组所有元素的标准差。
    • np.var(arr):计算数组所有元素的方差。
    • np.min(arr):找到数组中的最小值。
    • np.max(arr):找到数组中的最大值。
    • np.argmin(arr):找到数组中最小值的索引。
    • np.argmax(arr):找到数组中最大值的索引。
    arr1 = np.array([1, 2, 3, 4, 5])
    arr2 = np.array([6, 7, 8, 9, 10])
    
    # 计算数组总和
    sum_result = np.sum(arr1)
    print("数组总和:", sum_result)
    # 数组总和: 15
    
    # 计算数组平均值
    mean_result = np.mean(arr1)
    print("数组平均值:", mean_result)
    # 数组平均值: 3.0
    
    # 计算数组标准差
    std_result = np.std(arr1)
    print("数组标准差:", std_result)
    # 数组标准差: 1.4142135623730951
    
    # 计算数组最大值
    max_result = np.max(arr1)
    print("数组最大值:", max_result)
    # 数组最大值: 5
    

    广播机制

    广播机制(Broadcasting)是NumPy中一种强大且灵活的功能,它允许不同形状的数组在进行元素级别的运算时自动调整形状,以满足运算的要求。广播机制可以简化代码并提高计算的效率。

    广播机制的核心原则是在进行运算时,NumPy会自动调整数组的形状,使其能够逐元素地进行计算。具体来说,广播机制会按照以下规则进行数组的形状调整:

    1. 如果两个数组的维度数不同,那么在较小的维度上添加长度为1的维度,直到两个数组的维度数相同。
      a. 维度数(number of dimensions)是指数组的维度或轴的数量。在NumPy中,数组的维度数可以通过ndim属性获取
      b. 长度为1的维度指的是在数组的形状中,某个维度的长度(即元素个数)为1
    # 创建示例数组
    arr1 = np.array([1, 2, 3])  # 形状为 (3,)
    # [1 2 3]
    arr2 = np.array([[4], [5], [6]])  # 形状为 (3, 1)
    # [[4]
    #  [5]
    #  [6]]
    
    # 在较小维度上添加长度为1的维度,使维度数相同
    broadcasted_arr1 = arr1[:, np.newaxis]  # 添加维度后的形状为 (3, 1)
    
    print("调整后的数组形状:")
    print(broadcasted_arr1)
    # [[1]
    #  [2]
    #  [3]]
    print(arr2)
    # [[4]
    #  [5]
    #  [6]]
    
    1. 如果两个数组的维度长度相同,或者其中一个数组在某个维度上的长度为1,那么这两个数组在该维度上是兼容的。
      a. 二维数组中,第一维度:行数;第二维度:列数;
    # 创建示例数组
    arr1 = np.array([1, 2, 3])  # 形状为 (3,)
    # [1 2 3]
    arr2 = np.array([[4, 5, 6]])  # 形状为 (1, 3)
    # [[4 5 6]]
    
    # 在维度长度相同的情况下,数组在该维度上是兼容的
    result = arr1 + arr2
    
    print("运算结果:")
    print(result)
    # [[5 7 9]]
    
    1. 如果两个数组在所有维度上的长度都不相等,且其中没有一个数组的长度为1,则无法进行广播,会引发错误。
    # 创建示例数组
    arr1 = np.array([1, 2, 3])  # 形状为 (3,)
    # [1 2 3]
    arr2 = np.array([4, 5, 6, 7])  # 形状为 (4,)
    # [4 5 6 7]
    
    # 无法进行广播,会引发错误
    result = arr1 + arr2
    
    # 运行到此处时会抛出 ValueError: operands could not be broadcast together with shapes (3,) (4,) 错误
    
    

    广播机制的应用场景包括:

    • 对不同形状的数组进行元素级别的运算,如加法、乘法等。
    # 广播示例1: 不同形状的数组相加
    arr1 = np.array([1, 2, 3]) # 形状 (3, ) 维度 1
    arr2 = np.array([[4, 5, 6], [7, 8, 9]]) # 形状 (2, 3) 维度 2
    result2 = arr1 + arr2
    
    # 为了使它们的维度数相同,arr1会在其形状中添加一个长度为1的维度,变为 (1, 3)
    # [[1, 2, 3]]
    
    print("不同形状的数组相加结果:")
    print(result2)
    # [[ 5  7  9]
    #  [ 8 10 12]]
    
    • 在数组与标量之间进行运算,将标量广播到数组的每个元素。
    # 广播示例2: 数组与标量的运算
    
    scalar = 10
    arr1 = np.array([1, 2, 3])
    
    result1 = arr1 + scalar
    print("数组与标量的运算结果:")
    print(result1)
    # [11 12 13]
    
    • 在数组与更高维度的数组之间进行运算,使其形状兼容。

    数学函数及线性代数操作

    NumPy提供了广泛的数学函数和线性代数操作,可以对数组进行各种数学运算和矩阵操作。以下是一些常用的数学函数和线性代数操作示例:

    • np.sin(arr):计算数组中每个元素的正弦值。
    # 使用数学函数
    sin_result = np.sin(arr1)
    print("正弦值:", sin_result)
    
    • np.cos(arr):计算数组中每个元素的余弦值。
    • np.exp(arr):计算数组中每个元素的指数值。
    • np.log(arr):计算数组中每个元素的自然对数。
    • np.dot(arr1, arr2):计算两个数组的点积。
    # 进行矩阵乘法
    matrix1 = np.array([[1, 2], [3, 4]])
    # [[1 2]
    #  [3 4]]
    matrix2 = np.array([[5, 6], [7, 8]])
    # [[5 6]
    #  [7 8]]
    dot_result = np.dot(matrix1, matrix2)
    print("矩阵乘法结果:")
    print(dot_result)
    # [[19 22]
    #  [43 50]]
    
    • np.transpose(arr):计算数组的转置。
    matrix1 = np.array([[1, 2], [3, 4]])
    # [[1 2]
    #  [3 4]]
    
    # 计算数组的转置
    transpose_result = np.transpose(matrix1)
    print("数组转置结果:")
    print(transpose_result)
    # [[1 3]
    #  [2 4]]
    
    • np.linalg.inv(arr):计算数组的逆矩阵。
    matrix1 = np.array([[1, 2], [3, 4]])
    # [[1 2]
    #  [3 4]]
    
    # 计算数组的逆矩阵
    inv_result = np.linalg.inv(matrix1)
    print("逆矩阵结果:")
    print(inv_result)
    # [[-2.   1. ]
    #  [ 1.5 -0.5]]
    

    5. 数组的读写存储

    NumPy提供了方便的函数来读写和存储数组数据。在本节中,学习如何使用NumPy读取和写入数组数据。

    读写数组

    写入数组数据

    使用NumPy的np.save()函数。该函数将数组数据保存到二进制文件中,以便以后读取使用。

    # 创建一个数组
    arr = np.array([1, 2, 3, 4, 5])
    
    # 写入数组数据
    np.save('data.npy', arr)
    

    读取数组数据

    使用NumPy的np.load()函数。该函数从存储的二进制文件中加载数组,并返回一个包含数组数据的NumPy数组对象

    # 读取数组数据
    arr = np.load('data.npy')
    
    # 打印数组
    print(arr)
    

    存储与加载数组

    除了读写数组数据,NumPy还提供了更灵活的函数来存储和加载数组数据,如np.savez()和np.load()。

    使用np.savez()函数可以将多个数组保存到一个压缩文件.npz中。

    # 创建两个数组
    arr1 = np.array([1, 2, 3])
    arr2 = np.array([4, 5, 6])
    
    # 存储多个数组数据
    np.savez('data.npz', array1=arr1, array2=arr2)
    

    使用np.load()函数加载.npz文件时,它会返回一个类似于字典的对象,其中包含了被保存的数组数据。

    # 加载多个数组数据
    data = np.load('data.npz')
    
    # 访问数组数据
    arr1 = data['array1']
    arr2 = data['array2']
    
    # 打印数组
    print(arr1)
    print(arr2)
    

    6. 数组的统计计算

    在NumPy中,我们可以对数组进行各种统计计算。这些计算可以帮助我们了解数组中的数据分布、趋势和相关性等信息。

    基本统计计算

    平均值(mean):计算数组的平均值。
    标准差(std):计算数组的标准差,衡量数据的离散程度。
    方差(var):计算数组的方差,衡量数据的离散程度。
    最小值(min):找到数组中的最小值。
    最大值(max):找到数组中的最大值。
    总和(sum):计算数组中所有元素的总和。
    最小值索引(argmin):找到数组中最小值的索引。
    最大值索引(argmax):找到数组中最大值的索引。

    高级统计计算

    百分位数(percentiles):计算数组中给定百分比的元素值。

    arr = np.array([1, 2, 3, 4, 5]) 
    
    # 计算50%的百分位数【计算50%的百分位数就是返回数组中的中位数】
    percentile_value = np.percentile(arr, 50)  
    print(percentile_value)
    # 3.0
    
    # 找到一个值,使得10%的元素小于或等于这个值
    percentile_value = np.percentile(arr, 10)  
    print(percentile_value)
    # 1.4
    

    中位数(median):计算数组的中位数。

    arr = np.array([1, 2, 3, 4, 5])
    
    median_value = np.median(arr)
    print(median_value)
    # 3.0
    

    相关系数(corrcoef):计算数组的相关系数。

    arr1 = np.array([1, 2, 3, 4, 5])
    arr2 = np.array([5, 4, 3, 2, 1])
    
    corrcoef_value = np.corrcoef(arr1, arr2)
    print(corrcoef_value)
    # [[ 1. -1.]
    #  [-1.  1.]]
    

    协方差(cov):计算数组的协方差矩阵。

    arr1 = np.array([1, 2, 3, 4, 5])
    arr2 = np.array([5, 4, 3, 2, 1])
    
    cov_matrix = np.cov(arr1, arr2)
    print(cov_matrix)
    # [[ 2.5 -2.5]
    #  [-2.5  2.5]]
    

    直方图(histogram):计算数组的直方图。
    直方图是一种用于可视化数据分布的图形表示方法。
    它将数据划分为一系列称为“箱子”(或“柱”)的区间,并计算落入每个区间的数据点数量
    直方图可以帮助我们了解数据的分布情况、数据的集中程度和数据的离散程度。

    • hist 是一个包含每个区间内数据点数量的数组
    • bins 是一个包含划分的区间边界值的数组
    arr = np.array([1, 2, 3, 4, 5])
    
    hist, bins = np.histogram(arr)
    print(hist)
    print(bins)
    # [1 0 1 0 0 1 0 1 0 1]
    # [1.  1.4 1.8 2.2 2.6 3.  3.4 3.8 4.2 4.6 5. ]
    

    差分(diff):计算数组的差分值。
    差分操作将计算相邻元素之间的差值

    arr = np.array([1, 2, 3, 4, 5])
    
    diff_arr = np.diff(arr)
    print(diff_arr)
    # [1 1 1 1]
    

    梯度(gradient):计算数组的梯度。
    数组的梯度是指数组中相邻元素之间的变化率或斜率
    对于一维数组,梯度表示每个元素的变化幅度;
    对于多维数组,梯度表示在每个维度上的变化幅度。

    arr = np.array([1, 2, 3, 4, 5])
    gradient_arr = np.gradient(arr)
    print(gradient_arr)
    # [1. 1. 1. 1. 1.]
    

    7. 数组的复制和视图

    在 NumPy 中,对数组进行复制和视图操作是常见的操作之一。理解复制和视图的概念及其区别对于正确处理数组非常重要。本教程将介绍深度复制、浅复制和视图的概念以及它们之间的区别。

    深度复制

    深度复制是指创建一个完全独立于原始数组的新数组,即在内存中生成一个完全相同的副本。对复制后的数组进行修改不会影响原始数组。

    使用 copy() 方法可以进行深度复制。

    arr = np.array([1, 2, 3, 4, 5])
    arr_copy = arr.copy()
    
    # 修改复制后的数组,不会影响原始数组
    arr_copy[0] = 10
    
    print("原始数组:", arr)
    print("深度复制后的数组:", arr_copy)
    # 原始数组: [1 2 3 4 5]
    # 深度复制后的数组: [10  2  3  4  5]
    

    浅复制

    浅复制是指创建一个新的数组对象,但该对象与原始数组共享相同的数据内容。这意味着对浅复制后的数组进行修改会影响原始数组。

    使用切片操作view()方法可以进行浅复制。

    arr = np.array([1, 2, 3, 4, 5])
    arr_shallow_copy = arr[:]
    
    # 修改浅复制后的数组,会影响原始数组
    arr_shallow_copy[0] = 10
    
    print("原始数组:", arr)
    print("浅复制后的数组:", arr_shallow_copy)
    # 原始数组: [10  2  3  4  5]
    # 浅复制后的数组: [10  2  3  4  5]
    

    视图

    视图是指创建一个新的数组对象,与原始数组共享相同的数据内容,但具有不同的维度大小或形状。对视图进行修改会影响原始数组,反之亦然。

    使用view()方法可以创建视图。

    arr = np.array([1, 2, 3, 4, 5])
    arr_view = arr.view()
    
    # 修改视图的形状和大小
    arr_view.shape = (5, 1)
    arr_view[1] = 10
    
    print("原始数组:", arr)
    print("视图数组:", arr_view)
    # 原始数组: [ 1 10  3  4  5]
    # 视图数组: [[ 1]
    #  [10]
    #  [ 3]
    #  [ 4]
    #  [ 5]]
    

    相关文章

      网友评论

          本文标题:深入学习NumPy:掌握数组操作与应用的终极指南

          本文链接:https://www.haomeiwen.com/subject/ofguedtx.html