政安晨:【示例演绎】【Python】【Numpy数据处理】快速入门(三)—— 数组的操作

准备

这是Numpy数据处理的示例演绎系列文章的第三篇,我的前两篇文章为:

政安晨:【示例演绎】【Python】【Numpy数据处理】快速入门(一)icon-default.png?t=N7T8https://blog.csdn.net/snowdenkeke/article/details/136125773

政安晨:【示例演绎】【Python】【Numpy数据处理】快速入门(二)icon-default.png?t=N7T8https://blog.csdn.net/snowdenkeke/article/details/136127590

小伙伴们准备好环境后,咱们开始。

数组的索引和切片、合并与拆分、复制和排序、查找和筛选,以及改变数组结构、数组I/O等这些是数组操作的基本技术。

其中最抽象的是查找和筛选,但这也是数组操作中最重要、最精髓的一部分,在数组操作中用好查找和筛选才能避免使用循环这是数组操作的最高境界。

索引和切片

在Numpy中,索引和切片是常用的操作用于获取和修改数组中的元素。

索引是指通过指定元素的位置来访问数组中的值。

Numpy中的索引是从0开始的,可以使用方括号来指定索引位置。

例如,对于一个一维数组,可以使用array[index]来访问特定位置的值。

切片是指通过指定范围来访问数组中的一部分元素。

Numpy使用start:stop:step的形式来指定切片的范围。其中,start表示切片开始位置(包含),stop表示切片结束位置(不包含),step表示步长,默认为1。可以使用冒号来省略某个参数。

例如,对于一个一维数组,可以使用array[start:stop:step]来获取数组中指定范围的元素。

索引和切片也可以用于多维数组。

对于二维数组,可以使用array[row_index, column_index]来访问特定位置的值;

对于多维数组,可以使用array[index1, index2, index3, ...]来指定多个维度的索引位置。

除了获取值,索引和切片还可以用于修改数组中的元素,可以通过给特定位置赋值来修改该位置的值。

需要注意的是,Numpy中的索引和切片操作都返回一个新的数组,而不是原始数组的视图,如果需要修改原始数组,需要使用array.copy()方法创建一个副本。

先准备一些代码:

a = np.arange(9)# 最后一个元素
a[-1]# 返回第2到第5个元素
a[2:5] # 返回第0到第7个元素,步长为3
a[:7:3] # 返回逆序的数组
a[::-1] 

执行如下:

对于多维数组操作,NumPy数组比Python的列表更加灵活、强大。

假设有一栋楼,共2层,每层的房间都是3行4列,那我们可以用一个三维数组来保存每个房间的居住人数(也可以是房间面积等其他数值信息)。

# 2层3行4列
a = np.arange(24).reshape(2,3,4) 
a# 虽然可以这样索引
a[1][2][3]# 但这样才是规范的用法
a[1,2,3] # 所有楼层的第0行第0列
a[:,0,0] # 1层的所有房间,等价于a[0]或a[0,...]
a[0,:,:] # 所有楼层所有排的第1到第3列
a[:,:,1:3] # 2层每一行的最后一个房间
a[1,:,-1] 

执行如下:

上述代码可以看出,对多维数组索引或切片得到的结果的维度不是确定的。

特别注意:切片返回的数组不是原始数据的副本,而是指向与原始数组相同的内存区域数组切片不会复制内部数组数据,只是产生了原始数据的一个新视图。

代码如下:

a = np.arange(12).reshape(3,4)
a# 数组b是数组a的切片
b = a[1:,2:] 
b# 改变数组b的值,也会同时影响数组a
b[:,:] = 99 
ba

执行:

上述代码中,数组b是数组a的切片,当改变数组b的元素时,数组a也同时发生了改变,这就证明了切片返回的数组不是一个独立数组,而是指向与原始数组相同的内存区域。

改变数组结构

NumPy之所以拥有极高的运算速度,除了并行、广播和矢量化等技术因素外,其数组存储顺序和数组视图相互独立也是一个很重要的原因。

正因为如此,改变数组结构自然是非常便捷的操作,改变数组结构的操作通常不会改变所操作的数组本身的存储顺序,只是生成了一个新的视图。

np. resize( )函数是个例外,它不返回新的视图,而是真正改变了数组的存储顺序。

ndarray自带多个改变数组结构的方法,在大部分情况下学会ndarray.reshape( )函数即可,我们在前面已经多次用到该函数,在某些情况下,翻滚轴函数numpy.rollaxis( )才是最佳的选择,需要多花一些时间去了解它。

以下是改变数组结构的几个常用函数:

ndarray.reshape( ):按照指定的结构(形状)返回数组的新视图,不改变原数组。

ndarray.ravel( ):返回多维数组一维化的视图,不改变原数组。

ndarray.transpose( ):返回行变列的视图,不改变原数组。

ndarray.resize( ):按照指定的结构(形状)改变原数组,无返回值。

numpy.rollaxis( ):翻滚轴,返回新的视图,不改变原数组。

接下来继续演绎这几个改变数组结构的函数的用法

a = np.arange(12)# reshape()函数返回数组a的一个新视图,但不会改变数组a
b = a.reshape((3,4)) 
a.shape
b.shape
b is a
b.base is a# resize()函数没有返回值,但真正改变了数组a的结构
a.resize([4,3]) 
a.shape# 返回多维数组一维化的视图,但不会改变原数组
a.ravel() # 返回行变列的视图,但不会改变原数组
a.transpose() # 返回行变列的视图,等价于transpose()函数
a.T  # 翻滚轴,1轴变0轴
np.rollaxis(a, 1, 0) 

咱们构建一个列表:

演绎reshape

演绎resize

继续演绎

翻滚轴函数有一个很容易理解的应用,就是用它来实现图像的通道分离,下面的代码生成了一个宽为800像素、高为600像素的彩色随机噪声图,使用翻滚轴函数可以将其分离成RGB三个颜色通道。最后两行代码导入pillow模块,从而可以直观地看到这幅噪声图。

img = np.random.randint(0, 256, (600, 800, 3), dtype=np.uint8)
img.shape# 将图像数据分离成RGB三个颜色通道
r, g, b = np.rollaxis(img, 2, 0) r.shape, g.shape, b.shape# 导入pillow模块的Image
from PIL import Image # 显示随机生成的噪声图
Image.fromarray(img).show() 

演绎如下:

将图像数据分离:

这是上述代码随机生成的图像:

合并

NumPy数组一旦创建就不能再改变其元素数量。

如果要动态改变数组元素数量,只能通过合并或拆分的方法生成新的数组,对于刚上手NumPy的程序员来说,最大的困惑就是不能使用append( )函数向数组内添加元素,甚至都找不到append( )函数。其实,NumPy仍然保留了append( )函数,只不过这个函数不再是数组的函数,而是升级到最外层的NumPy命名空间了,并且该函数的功能不再是追加元素,而是合并数组,其代码如下:

np.append([[1, 2, 3]], [[4, 5, 6]])np.append([[1, 2, 3]], [[4, 5, 6]], axis=0)np.append([[1, 2, 3]], [[4, 5, 6]], axis=1)

演绎:

不过,append( )函数还不够好用,推荐使用stack( )函数及其兄弟函数:hstack( )水平合并函数、vstack( )垂直合并函数和dstack( )深度合并函数。

接下来演绎这三个函数的用法:

a = np.arange(4).reshape(2,2)
b = np.arange(4,8).reshape(2,2)# 水平合并
np.hstack((a,b)) # 垂直合并
np.vstack((a,b)) # 深度合并
np.dstack((a,b)) 

演绎:

stack( )函数使用axis轴参数指定合并的规则,请演绎下面例子中axis轴参数的用法。

a = np.arange(60).reshape(3,4,5)
b = np.arange(60).reshape(3,4,5)
a.shape, b.shape
np.stack((a,b), axis=0).shapenp.stack((a,b), axis=1).shapenp.stack((a,b), axis=2).shapenp.stack((a,b), axis=3).shape

演绎如下:

拆分

因为数组切片非常简单,所以数组拆分应用较少,拆分是合并的逆过程,最常用的函数是split( ),其代码如下:

a = np.arange(16).reshape(2,4,2)# 水平方向拆分成2部分
np.hsplit(a, 2) # 垂直方向拆分成2部分
np.vsplit(a, 2) # 深度方向拆分成2部分
np.dsplit(a, 2) 

演绎,水平方向拆分成2部分:

演绎,垂直方向拆分成2部分:

演绎,深度方向拆分成2部分:

复制

改变数组结构返回的是原数组的一个新视图,而不是原数组的副本,浅复制(view)和深复制(copy)则是创建原数组的副本,但二者之间也有细微差别:

浅复制(view)是共享内存,深复制(copy)是独享内存

代码如下

a = np.arange(6).reshape((2,3))
b = a.view()
b is a
b.base is ab.flags.owndata
c = a.copy()c is ac.base is ac.flags.owndata

演绎上述代码第一部分:

演绎上述代码第二部分:

排序

NumPy数组有两个排序函数,一个是sort( ),另一个是argsort( ),sort( )函数返回输入数组的排序副本,argsort( )函数返回的是数组值从小到大的索引号,从函数原型看,这两个函数的参数完全一致。

numpy.sort(arr, axis=-1, kind='quicksort', order=None)
numpy.argsort(arr, axis=-1, kind='quicksort', order=None)

第1个参数arr,是要排序的数组;

第2个参数axis,也就是轴,指定排序的轴,默认值-1表示没有指定排序轴,返回结果将沿着最后的轴排序;

第3个参数kind,表示排序方法,默认为“quicksort”(快速排序),其他选项还有“mergesort”(归并排序)和“heapsort”(堆排序);

第4个参数order,指定用于排序的字段,前提是数组包含该字段。

a = np.random.random((2,3))
a# 返回行内从小到大排序的索引号(列排序),相当于axis=1(最后的轴)
np.argsort(a) # 返回行内从小到大排序的一个新数组(列排序)
np.sort(a) # 返回列内从小到大排序的一个新数组(行排序)
np.sort(a,axis=0)

演绎如下:

下面演绎的是排序字段的使用,先定义一个新的数据类型dt,它类似于一个字典,有姓名name和年龄age两个键值对,姓名的长度为10个字符,年龄的数据类型是整型。

代码如下:

dt = np.dtype([('name',  'S10'),('age',  int)])
a = np.array([("zh",21),("wang",25),("li",17),  ("zhao",27)], dtype = dt)# 如果指定姓名排序,结果是李王张赵
np.sort(a, order='name') # 如果指定年龄排序,结果则是李张王赵
np.sort(a, order='age') 

演绎如下:

查找

这里约定查找是返回数组中符合条件的元素的索引号,或返回和数组具有相同结构的布尔型数组,元素符合条件在布尔型数组中对应True,否则对应False,查找分为最大值和最小值查找非零元素查找使用逻辑表达式查找使用where条件查找这4种方式。

1. 最大值和最小值查找

下面的代码演示了返回数组中最大值和最小值的索引号,如果是多维数组,这个索引号是数组转成一维之后的索引号:

a = np.random.random((2,3))
anp.argmax(a)np.argmin(a)

演绎:

2. 非零元素查找

下面的代码演示了返回数组中非零元素的索引号,返回的结果是一个元组:

a = np.random.randint(0, 2, (2,3))
anp.nonzero(a)

演绎:

3. 使用逻辑表达式查找

下面的代码演示了使用逻辑表达式查找符合条件的元素,返回结果是一个和原数组结构相同的布尔型数组,元素符合条件在布尔型数组中对应True,否则对应False。

代码如下:

a = np.arange(10).reshape((2,5))
a(a>3)&(a<8)

演绎如下:

4. 使用where条件查找

np.where( )函数返回数组中满足给定条件的元素的索引号,其结构为元组,元组的第k个元素对应符合条件的元素在数组k轴上的索引号。这句话可以简单理解为,一维数组返回一个元素的元组,二维数组返回两个元素的元组,依此类推。np.where( )函数还可以用于替换符合条件的元素。

代码如下:

a = np.arange(10)
anp.where(a < 5)a = a.reshape((2, -1))
anp.where(a < 5)# 满足条件的元素不变,其他元素乘10
np.where(a < 5, a, 10*a) 

演绎如下:

筛选

筛选是返回符合条件的元素。

筛选条件有三种表示方式:

一是使用np.where( )函数返回的Python元组。

二是使用逻辑表达式返回的布尔型数组。

三是使用整型数组。

其代码如下:

a = np.random.random((3,4))
a# 返回大于0.5的元素(使用np.where()函数返回的Python元组)
a[np.where(a>0.5)]# 返回大于0.3且小于0.7的元素(使用逻辑表达式返回的布尔型数组)
a[(a>0.3)&(a<0.7)]# 返回整型数组指定的项(使用整型数组)
a[np.array([2,1])] a = a.ravel()# 返回整型数组指定的项(使用整型数组)
a[np.array([3,5,7,11])] # 返回整型数组指定的项(使用整型数组)
a[np.array([[3,5],[7,11]])] 

演绎如下:

告一段落

咱们先演绎到这里,基本完成了Numpy对数组操作的感知。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/685475.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

计算机设计大赛 深度学习YOLO安检管制物品识别与检测 - python opencv

文章目录 0 前言1 课题背景2 实现效果3 卷积神经网络4 Yolov55 模型训练6 实现效果7 最后 0 前言 &#x1f525; 优质竞赛项目系列&#xff0c;今天要分享的是 &#x1f6a9; **基于深度学习YOLO安检管制误判识别与检测 ** 该项目较为新颖&#xff0c;适合作为竞赛课题方向&…

17.3.1.5 二值化(黑白)

版权声明&#xff1a;本文为博主原创文章&#xff0c;转载请在显著位置标明本文出处以及作者网名&#xff0c;未经作者允许不得用于商业目的。 二值化的算法主要有以下两种&#xff1a; 1、彩色图像灰度化后&#xff0c;根据灰度和阈值来确定颜色是黑色还是白色。通常情况下使…

STM32

Unix时间戳 BKP 读写备份寄存器 main.c #include "stm32f10x.h" // Device header #include "Delay.h" #include "OLED.h" #include "Key.h"uint8_t KeyNum;uint16_t ArrayWrite[] {0x1234,0x2134}; uint16_t Arr…

Nvidia 携手 RTX 推出的本地运行 AI 聊天机器人

每周跟踪AI热点新闻动向和震撼发展 想要探索生成式人工智能的前沿进展吗&#xff1f;订阅我们的简报&#xff0c;深入解析最新的技术突破、实际应用案例和未来的趋势。与全球数同行一同&#xff0c;从行业内部的深度分析和实用指南中受益。不要错过这个机会&#xff0c;成为AI领…

2024.2.16日总结(小程序开发8)

数据监听器 监听对象属性的变化 数据监听器支持监听对象中单个或多个属性的变化 纯数据字段 什么是纯数据字段 纯数据字段指的是哪些不用于页面渲染的data字段 应用场景:例如有些情况下&#xff0c;某些 data 中的字段既不会展示在界面上&#xff0c;也不会传递给其他组件…

html从零开始9:javaScript简介,语句、标识符,变量,JavaScript引入到文件【搬代码】

javaScript简介 javaScript语句、标识符 变量 var num 10; var就是固定声明,num就是变量名&#xff0c;10就是变量&#xff1b;<!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><meta http-equiv"X-UA-Comp…

Flutter 动画(显式动画、隐式动画、Hero动画、页面转场动画、交错动画)

前言 当前案例 Flutter SDK版本&#xff1a;3.13.2 显式动画 Tween({this.begin,this.end}) 两个构造参数&#xff0c;分别是 开始值 和 结束值&#xff0c;根据这两个值&#xff0c;提供了控制动画的方法&#xff0c;以下是常用的&#xff1b; controller.forward() : 向前…

Docker笔记-搭建Python环境、安装依赖、打包镜像、导入镜像、编写bash脚本灵活调用

说明 适合无联网的机器及多Python的机器进行部署。 制作docker版Python环境 有网络及有docker的&#xff0c;拉取指定版本的python如&#xff1a; docker pull python:3.7 安装好后进入容器&#xff1a; docker run -it <name> /bin/bash 使用pip安装各种依赖&…

Redis -- 数据库管理

目录 前言 切换数据库(select) 数据库中key的数量&#xff08;dbsize&#xff09; 清除数据库&#xff08;flushall flushdb&#xff09; 前言 MySQL有一个很重要的概念&#xff0c;那就是数据库database&#xff0c;一个MySQL里面有很多个database&#xff0c;一个datab…

Simulink模块说明

Simulink库 Commonly Used Blocks Bus Creator 将一组输入元素合并成一条总线**输入&#xff1a;**要包含在总线中的输入元素。**输出&#xff1a;**由合并的输入元素组成的输出总线&#xff0c;指定为虚拟或非虚拟总线。 Bus Selector Bus Selector 模块输出您从输入总线选…

《白话C++》第9章 泛型,Page842~844 9.4.2 AutoPtr

源起&#xff1a; C编程中&#xff0c;最容易出的问题之一&#xff0c;就是内存泄露&#xff0c;而new一个对象&#xff0c;却忘了delete它&#xff0c;则是造成内存泄露的主要原因之一 例子一&#xff1a; void foo() {XXXObject* xo new XXXObject;if(!xo->DoSomethin…

Web项目利用MybatisPlus进行分页查询

之前在写博客系统前台页面的时候&#xff0c;遇到了利用mp进行分页查询的情况&#xff0c;由于涉及到的知识点相对较为重要&#xff0c;固写一篇博客以此巩固。 一、功能需求 在首页和分类页面都需要查询文章列表。 首页&#xff1a;查询所有的文章分类页面&#xff1a;查询…

[计算机网络]---序列化和反序列化

前言 作者&#xff1a;小蜗牛向前冲 名言&#xff1a;我可以接受失败&#xff0c;但我不能接受放弃 如果觉的博主的文章还不错的话&#xff0c;还请点赞&#xff0c;收藏&#xff0c;关注&#x1f440;支持博主。如果发现有问题的地方欢迎❀大家在评论区指正 目录 一、再谈协议…

【NLP】MHA、MQA、GQA机制的区别

Note LLama2的注意力机制使用了GQA。三种机制的图如下&#xff1a; MHA机制&#xff08;Multi-head Attention&#xff09; MHA&#xff08;Multi-head Attention&#xff09;是标准的多头注意力机制&#xff0c;包含h个Query、Key 和 Value 矩阵。所有注意力头的 Key 和 V…

springboot189基于SpringBoot电商平台的设计与实现

简介 【毕设源码推荐 javaweb 项目】基于springbootvue 的 适用于计算机类毕业设计&#xff0c;课程设计参考与学习用途。仅供学习参考&#xff0c; 不得用于商业或者非法用途&#xff0c;否则&#xff0c;一切后果请用户自负。 看运行截图看 第五章 第四章 获取资料方式 **项…

安全基础~通用漏洞5

文章目录 知识补充CSRFSSRFxss与csrf结合创建管理员账号 知识补充 NAT&#xff1a;网络地址转换&#xff0c;可以将IP数据报文头中的IP地址转换为另一个IP地址&#xff0c;并通过转换端口号达到地址重用的目的。即通过将一个外部IP地址和端口映射更大的内部IP地址集来转换IP地…

ICLR 2023#Learning to Compose Soft Prompts for Compositional Zero-Shot Learning

组合零样本学习&#xff08;CZSL&#xff09;中Soft Prompt相关工作汇总&#xff08;一&#xff09; 文章目录 组合零样本学习&#xff08;CZSL&#xff09;中Soft Prompt相关工作汇总&#xff08;一&#xff09;ICLR 2023#Learning to Compose Soft Prompts for Compositional…

透光卓越,光耦继电器的独特特点全面解析

光耦继电器作为电子控制系统中的核心元件&#xff0c;其光电隔离技术为其独特之处。通过光电隔离技术&#xff0c;光耦继电器实现了输入和输出之间的电气隔离&#xff0c;有效阻止了高电压与低电压之间的直接接触。这项技术不仅提高了系统的安全性&#xff0c;还有效减少了电气…

Vue练习1:组件开发1(头像组件)

样式预览 注释代码 <template><div class"img-box":style"{ //动态style必须为对象width: size rem,height: size rem}"><imgclass"avatar-img":src"url" //动态url/></div> </templ…

【DDD】学习笔记-聚合设计原则

聚合设计原则 对比对象图和聚合&#xff0c;我们认为引入聚合的目的是控制对象之间的关系&#xff0c;这实则是引入聚合的技术原因。领域驱动设计引入聚合&#xff08;Aggregate&#xff09;来划分对象之间的边界&#xff0c;在边界内保证所有对象的一致性&#xff0c;并在对象…