numpy基础

文章目录


引言:numpy的常见注意事项

1 numpy数组是可变数据类型

NumPy 数组(numpy.ndarray)是 可变数据类型

以下是一些关键点来解释 NumPy 数组的可变性:

(1). 元素的修改

  • NumPy 数组中的元素是可以被修改的。你可以直接通过索引来改变数组中的某个值。例如,给定一个数组 arr,你可以通过 arr[0] = 10 来修改数组的第一个元素。
import numpy as np

arr = np.array([1, 2, 3])
arr[0] = 10  # 修改第一个元素为 10
print(arr)   # 输出: [10  2  3]

(2). 数据的视图与切片

  • NumPy 提供了一种称为视图(view)的机制,通过该机制可以从一个数组创建一个新的数组对象,而不复制数据本身。这意味着通过一个视图修改数组中的元素也会影响到原始数组。
arr = np.array([1, 2, 3, 4])
view = arr[1:3]  # 创建一个视图
view[0] = 10     # 修改视图中的元素
print(arr)       # 输出: [ 1 10  3  4],原始数组也被修改

(3). 内存共享

  • 多个数组可以共享相同的数据内存。例如,通过 np.copy 创建的数组和通过 view 创建的数组都可以共享同一块内存。这种机制增强了数组的可变性,因为一个数组的修改可能会影响到共享同一内存的其他数组。

综上所述,NumPy 数组允许对其内容进行修改,并且这种修改会反映在使用该数组的所有视图中,这表明它是可变的。

2 numpy数组的view视图机制以及与列表的区别

2.1 numpy数组的view机制

NumPy 的视图(view)机制是一种允许多个数组对象共享相同数据内存的方法。通过这种机制,创建一个数组的视图(view)不会复制数据本身,而是创建一个新的数组对象,该对象使用与原始数组相同的内存。因此,对视图的修改会影响原始数组,反之亦然。(简单来说就是numpy数组的赋值操作是共享原内存的。)

2.1.1视图机制的工作原理

视图机制的关键在于 NumPy 数组的设计。每个 numpy.ndarray 对象包括以下几个部分:

  • 数据缓冲区:实际存储数组数据的内存区域。
  • 形状信息:定义数组的维度和每个维度的大小。
  • 步长信息:定义在数组的每个维度上前进一个元素所需跳过的字节数。

视图与原数组共享相同的数据缓冲区,但它们可以拥有不同的形状和步长信息,这使得视图可以表现为不同的数组结构。

2.1.2视图的创建方式

(1). 数组切片(Slicing)
使用切片操作可以创建一个数组的视图。切片操作不会创建数据的副本,而是生成一个新的数组对象,该对象仍然引用原始数据。

import numpy as np

arr = np.array([1, 2, 3, 4, 5])
view = arr[1:4]  # 创建视图
view[0] = 10     # 修改视图中的元素
print(arr)       # 输出: [ 1 10  3  4  5],原始数组也被修改
print(view)      # 输出: [10  3  4]

(2). 数组的变形(Reshape):— 特别注意这个也是内存共享的在numpy里面没有想到吧
使用 reshape 方法重新定义数组的形状,也会创建一个视图,只要新形状与原数组兼容且没有引入新的内存布局(如展平操作)。

arr = np.array([[1, 2, 3], [4, 5, 6]])
view = arr.reshape(3, 2)  # 创建视图
view[0, 0] = 10
print(arr)               # 输出: [[10  2  3]
                         #      [ 4  5  6]],原始数组被修改
print(view)              # 输出: [[10  2]
                         #      [ 3  4]
                         #      [ 5  6]]

(3). 数组的转换操作(Transpose)
使用 transposeT 属性可以创建一个转置视图。

arr = np.array([[1, 2], [3, 4]])
view = arr.T  # 创建转置视图
view[0, 1] = 10
print(arr)   # 输出: [[ 1  2]
             #      [ 10  4]],原始数组被修改
print(view)  # 输出: [[ 1  10]
             #      [2   4]]

总结一下就是,numpy的view机制就是让将原本的赋值给新变量应该是创建一个新内存,但numpy的view视图机制 ---- 就是让赋值操作不改变内存,还是共享原来的内存。

arr = np.array([1, 2, 3, 4])

arr2 = arr
arr2[0] = 100

print(arr)         # [100   2   3   4]
print(arr2)        # [100   2   3   4]

arr 和arr2的内存是共享的,这就是numpy数组的view视图机制的神奇之处,也是我们需要注意的地方。
【注】:numpy数组变成就是进行的是赋值操作也要想想是不是内存共享的。

2.2 numpy view机制与列表(没有view机制的数据结构)的区别

看下面前先了解列表的浅复制与深复制python列表
NumPy 的视图(view)机制和 Python 列表之间有着显著的差异,尤其在内存管理和数据操作方面。下面我们详细对比 NumPy 数组的视图机制与 Python 列表的特性。

1. 内存管理
NumPy 数组的视图
  • 共享内存

    • NumPy 数组的视图和原数组共享相同的内存空间。任何对视图的修改都会直接反映在原数组上,反之亦然。
    • 视图(view)是通过操作原数组的元数据(如形状、步长等)而产生的,不涉及数据的复制。
    import numpy as np
    
    arr = np.array([1, 2, 3, 4])
    view = arr[1:3]   # 创建一个视图
    view[0] = 10      # 修改视图中的值
    print(arr)        # 输出: [ 1 10  3  4],原始数组被修改
    print(view)       # 输出: [10  3],视图反映出修改
    
  • 内存连续性

    • NumPy 数组通常是内存连续的,这意味着数据在内存中是按顺序排列的,这对计算效率有很大的提升。
    • 视图可以通过步长(strides)和形状信息创建,从而允许非常高效地操作数组的子集或重塑数组。
Python 列表
  • 独立内存

    • Python 列表没有视图机制。每个列表元素的引用是独立的,创建子列表时会复制引用(浅拷贝),但不会共享相同的内存空间。即使是子列表,对它的修改不会影响原始列表。
    • 深拷贝和浅拷贝的概念在列表中尤为重要。浅拷贝会创建一个新列表,其中的元素是原列表中对象的引用,而深拷贝则会递归地复制整个对象及其子对象。
    lst = [1, 2, 3, 4]
    sub_lst = lst[1:3]  # 创建一个子列表(浅拷贝)
    sub_lst[0] = 10     # 修改子列表中的值
    print(lst)          # 输出: [1, 2, 3, 4],原始列表未被修改
    print(sub_lst)      # 输出: [10, 3],子列表显示修改
    
  • 内存分散

    • 列表中的元素是独立存储的引用,存储地址可能不连续。这种非连续性使得某些操作的效率较低,特别是与数值运算相关的操作。
2. 数据操作
NumPy 数组的视图
  • 高效的切片与变形

    • NumPy 允许通过视图对数组进行非常高效的切片、重塑和操作,而无需实际的数据复制。可以通过视图进行快速的子数组操作。
    arr = np.array([1, 2, 3, 4, 5, 6])
    reshaped = arr.reshape((2, 3))  # 重塑数组,不复制数据
    print(reshaped)                 # 输出: [[1 2 3]
                                    #      [4 5 6]]
    
  • 内存高效性

    • 由于视图共享内存,操作大数据集时无需担心内存的过度使用。许多数值操作可以在原地进行,减少了内存的开销。
Python 列表
  • 切片创建新列表
    • 切片操作创建一个新的列表(浅拷贝),这意味着元素的引用被复制了,但实际的数据没有复制。如果原始列表包含的不是简单数据类型,而是对象,修改对象会影响到切片和原列表。
    • 但如果是顶层不可变数据,浅拷贝是修改是不会影响原列表的
ls = [1,[2,3],4,5]
a = ls[1:3]       # [[2, 3], 4]        将列表切片进行赋值给变量a。本质上就是浅拷贝
a[1] = 100 

print(a)          # [[2, 3], 100]              
print(ls)         # [1, [2, 3], 4, 5]      浅拷贝修改顶层不影响原列表

a[0][0] = 200 
print(ls)         # [1, [200, 3], 4, 5]     浅拷贝修改内层可变数据类型会影响原列表
  • 深拷贝

    • 如果需要真正独立的副本,必须使用深拷贝(copy.deepcopy),这会递归地复制列表及其包含的所有元素。深拷贝在需要隔离修改时非常重要,但它比视图操作的效率低得多。
    import copy
    
    lst = [[1, 2], [3, 4]]
    deep_copy_lst = copy.deepcopy(lst)
    deep_copy_lst[0][0] = 10
    print(lst)          # 输出: [[1, 2], [3, 4]],原始列表未受影响
    print(deep_copy_lst)  # 输出: [[10, 2], [3, 4]],深拷贝反映出修改
    

2.3 视图与副本的区别

看下面前先了解列表的浅复制与深复制python列表
视图(view)和副本(copy)的主要区别在于内存共享:

  • 视图:多个数组对象共享相同的数据内存,对其中任何一个的修改都会反映在所有视图中。
  • 副本:副本是原数据的完全独立的克隆,修改副本不会影响原始数组,反之亦然。把副本理解成深拷贝就行了。
  • 在numpy数组里面数据
  • 注意,numpy自带的 .copy方法是深复制,和copy模块的copy方法是浅复制不一样
arr = np.array([1, 2, 3, 4])
view = arr[1:3]     # 创建视图
copy = arr[1:3].copy()  # 创建副本

view[0] = 10
copy[0] = 20

print(arr)  # 输出: [ 1 10  3  4],视图的修改影响原数组
print(view) # 输出: [10  3]
print(copy) # 输出: [20  3],副本的修改不影响原数组

二维数组

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

copy = arr[:,0].copy()  # 创建副本,numpy自带的是深复制
print(copy)  # 输出: [1 4 7]

copy[0] = 20
print(arr)  # 输出: [[1 2 3] [4 5 6] [7 8 9]],副本的修改不影响原数组
print(copy) # 输出: [20  4  7],副本的修改不影响原数组

【注】:在numpy数组中由于有自带的 .copy(深复制)就不要和列表一样用copy模块了。另外由于numpy数组特殊的视图机制,如果用copy模块里面浅复制,两者结合在一起会导致浅复制效果和深复制效果一样。之前列表那套规则完全不适用,就不用管了。

2.4 视图的优势

  • 效率:视图避免了数据复制,因此可以显著节省内存和时间,尤其是处理大型数据集时。
  • 灵活性:可以通过视图创建不同的数组视图,进行不同的操作,而无需改变原始数组的数据。

NumPy 的视图机制是高效数据操作的核心特性,理解和正确使用它有助于优化数组操作的性能。

一、numpy数组创建

1. np.array(object,dtype)

np.array() 是 NumPy 中用于创建数组的函数,它将输入的数据转换为 NumPy 数组。以下是 np.array() 函数的两个常用参数及其详细说明,其他参数默认值即可:

(1). object:输入的数据对象,可以是以下类型之一:

  • Python 列表或元组:[1, 2, 3], (1, 2, 3)
  • 嵌套列表或元组:[[1, 2], [3, 4]], ((1, 2), (3, 4))
  • 可迭代对象:如 Python 迭代器、生成器等

(2). dtype:(可选参数)所需的输出数据类型。如果未提供,NumPy 将自动推断数据类型。常见的数据类型包括:

  • int, float, complex: 整数、浮点数、复数
  • bool: 布尔值
  • str: 字符串
  • 其他数据类型:如 np.int32, np.float64
arr1 = np.array([1,2,3])
print(arr1)             # 输出 [1,2,3]

arr2 = np.array([[1,2,3],
                 [4,5,6]], dtype=np.float64)
print(arr2)             # 输出 [[1. 2. 3.]
                        #      [4. 5. 6.]]

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

左闭右开
np.arange() 是 NumPy 库中的一个函数,用于创建一个按指定范围和间隔的等差数组。

参数说明:

  • start:可选,表示起始值,默认为0。
  • stop:结束值(不包含在数组内)。
  • step:可选,表示步长(增量),默认为1。如果未指定步长,会自动使用1。
  • dtype:可选,返回数组的数据类型。如果未提供,则会根据其他输入推断数据类型。

np.arange() 返回的是一个 NumPy 数组,其中包含从 startstop(不包含 stop)之间,以 step 为步长的一系列数值。

arr1 = np.arange(1,10
  • 20
    点赞
  • 23
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
NumPy是一个功能强大的Python库,主要用于对多维数组执行计算。它的使用可以使代码更简洁,并且具有一些特性,如向量化操作,可以加速计算过程。在NumPy中,最重要的数据结构是NumPy数组,它可以通过不同的方法进行创建。 创建一维NumPy数组的常见方法有以下几种: 1. 使用np.array()函数,传入一个列表作为参数,例如: my_array = np.array([1, 2, 3, 4, 5]) 2. 使用np.array()函数,传入一个元组作为参数,例如: my_array2 = np.array((0, 1, 2, 3, 4)) 3. 使用np.arange()函数,该函数类似于内置函数range(),返回一个数组而不是列表,例如: my_array3 = np.arange(5) 4. 使用np.linspace()函数,该函数返回一个包含指定数量元素的数组,而不是指定步长(step),例如: my_array4 = np.linspace(0, 2*np.pi, 5) 这些方法可以用来创建不同类型的一维NumPy数组。通过打印数组可以查看创建的结果。在使用NumPy之前,需要导入NumPy库,可以使用import numpy as np语句进行导入。 NumPy还可以用于执行各种数学任务,如数值积分、微分、内插、外推等,以及快速处理图像等。因此,在机器学习中,NumPy常被用于存储训练数据和机器学习模型的参数,以及进行简单和快速的计算。 总结起来,NumPy提供了丰富的功能和优秀的库函数,使得在Python中进行数值计算变得更加方便和高效。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* [python科学计算的基本包-Python科学计算基本包Numpy使用的教程.pdf](https://download.csdn.net/download/qq_43934844/87898289)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] - *2* *3* [numpy基础语法整理](https://blog.csdn.net/weixin_61890283/article/details/124596265)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值