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

news2024/12/29 10:55:14

准备

这是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 
b

a

执行:

上述代码中,数组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).shape

np.stack((a,b), axis=1).shape

np.stack((a,b), axis=2).shape

np.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 a


b.flags.owndata
c = a.copy()

c is a

c.base is a

c.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))
a

np.argmax(a)

np.argmin(a)

演绎:

2. 非零元素查找

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

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

np.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)
a

np.where(a < 5)

a = a.reshape((2, -1))
a

np.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.coloradmin.cn/o/1451860.html

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

相关文章

挑战杯 python的搜索引擎系统设计与实现

0 前言 &#x1f525; 优质竞赛项目系列&#xff0c;今天要分享的是 &#x1f6a9; python的搜索引擎系统设计与实现 &#x1f947;学长这里给一个题目综合评分(每项满分5分) 难度系数&#xff1a;3分工作量&#xff1a;5分创新点&#xff1a;3分 该项目较为新颖&#xff…

心理辅导|高校心理教育辅导系统|基于Springboot的高校心理教育辅导系统设计与实现(源码+数据库+文档)

高校心理教育辅导系统目录 目录 基于Springboot的高校心理教育辅导系统设计与实现 一、前言 二、系统功能设计 三、系统实现 1、学生功能模块的实现 &#xff08;1&#xff09;学生登录界面 &#xff08;2&#xff09;留言反馈界面 &#xff08;3&#xff09;试卷列表界…

娱乐直播APP开发:引领潮流,创新无界

随着互联网技术的飞速发展&#xff0c;娱乐直播APP已经成为现代人生活的重要组成部分。它以其独特的互动性、即时性和个性化&#xff0c;吸引了大量用户。本文将深入探讨娱乐直播APP开发的关键要素&#xff0c;以及如何在这个竞争激烈的市场中脱颖而出。 一、娱乐直播APP的核心…

http“超级应用与理解”

本篇文章来介绍一下http协议和其应用 1.http协议是在OSI模型的哪一层 HTTP&#xff08;超文本传输协议&#xff09;是应用层协议&#xff0c;它是在 OSI 模型的最高层&#xff0c;即第七层——应用层。HTTP 通过互联网来传输数据和信息&#xff0c;主要用于 Web 浏览器和 Web …

关于DVWA靶场Command Injection(命令注入)乱码的解决方案

乱码如下图&#xff1a; 出现乱码一般都是编码方式的问题&#xff0c;我们只需要对其换一种编码方式输出即可 靶场在 WWW 目录下&#xff0c;在靶场所在路径下有一个 dvwa 文件夹 进入之后找到 includes 文件夹 进入找到文件 dvwaPage.inc.php 右键&#xff0c;使用记事本打开…

ZYNQ:PL-CAN总线功能应用

流程背景 前期基本实现PS端的CAN总线功能&#xff0c;现阶段的主要目的是实现PL端的CAN总线功能&#xff0c;需要采用CAN IP。 PL系统搭建 PL外设时钟源 搭建完vivado系统后&#xff0c;需要在sdk编程。但是在配置PL&#xff0d;CAN时&#xff0c;意识到CAN时钟值不清楚&…

【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…

铱塔 (iita) 开源 IoT 物联网开发平台,基于 SpringBoot + TDEngine +Vue3

01 铱塔 (iita) 物联网平台 铱塔智联 (open-iita) 基于Java语言的开源物联网基础开发平台&#xff0c;提供了物联网及相关业务开发的常见基础功能, 能帮助你快速搭建自己的物联网相关业务平台。 铱塔智联平台包含了品类、物模型、消息转换、通讯组件&#xff08;mqtt/EMQX通讯组…

第7章 Page449~451 7.8.9智能指针 std::shared_ptr

“shared_ptr”是“共享式智能指针”。 即多个“shared_ptr”之间可以管理同一个裸指针。于是 O* o new O; //一个裸指针 std::shared_ptr <O> p1(o); //交给p1管 std::shared_ptr <O> p2(o); //又交给p2管 出乎意料&#xff0c;以上代码仍然是可以通过编译但运…

云计算基础-大页内存

大页内存功能概述 什么是大页内存 简单来说&#xff0c;就是通过增大操作系统页的大小来减小页表&#xff0c;从而避免快表缺失 主要应用场景 主要运用于内存密集型业务的虚拟机&#xff0c;比如对于运行数据库系统的虚拟机&#xff0c;采用HugePages(大页)后&#xff0c;可…

《区块链公链数据分析简易速速上手小册》第1章:区块链基础(2024 最新版)

文章目录 1.1 区块链技术概览&#xff1a;深入探究与实用案例1.1.1 区块链的核心概念1.1.2 重点案例&#xff1a;供应链管理1.1.3 拓展案例 1&#xff1a;数字身份验证1.1.4 拓展案例 2&#xff1a;智能合约在房地产交易中的应用 1.2 主流公链介绍1.2.1 公链的核心概念1.2.2 重…

Qt for android : Qt6.6.2 搭建 环境

环境说明 参考Qt助手: Assistant 6.6.2 (MinGW 11.2.0 64-bit) ***Gradle : Gradle wrapper, version 8.3***JDK11 SDK Tools / NDK 25.1.8937393 参考 Qt For Android : Qt5.13.1 Qt for android: Qt6.4搭建环境遇到的几个问题

MySQL数据库基础(五):SQL语言讲解

文章目录 SQL语言讲解 一、SQL概述 二、SQL语句分类 1、DDL 2、DML 3、DQL 4、DCL 三、SQL基本语法 1、SQL语句可以单行或多行书写&#xff0c;以分号结尾 2、可使用空格和缩进来增强语句的可读性 3、MySQL数据库的SQL语句不区分大小写&#xff0c;关键字建议使用大写…

MongoDB从入门到实战之.NET Core使用MongoDB开发ToDoList系统(3)-系统数据集合设计

前言 前几章教程我们把ToDoList系统的基本框架搭建好了&#xff0c;现在我们需要根据我们的需求把ToDoList系统所需要的系统集合&#xff08;相当于关系型数据库中的数据库表&#xff09;。接下来我们先简单概述一下这个系统主要需要实现的功能以及实现这些功能我们需要设计那些…

开源PDF工具 Apache PDFBox 认识及使用(知识点+案例)

文章目录 前言源码获取一、认识PDFBox二、导入依赖三、基础功能demo1&#xff1a;读取pdf所有内容demo2&#xff1a;读取所有页内容&#xff08;分页&#xff09;demo3&#xff1a;添加页眉、页脚demo4&#xff1a;添加居中45文字水印demo5&#xff1a;添加图片到右上角 参考文…

云计算基础-存储基础

存储概念 什么是存储&#xff1a; 存储就是根据不同的应用程序环境&#xff0c;通过采取合理、安全、有效的方式将数据保存到某些介质上&#xff0c;并能保证有效的访问&#xff0c;存储的本质是记录信息的载体。 存储的特性&#xff1a; 数据临时或长期驻留的物理介质需要保…

【打工日常】使用docker部署可视化工具docker-ui

一、docker-ui介绍 docker-ui是一个易用且轻量化的Docker管理工具&#xff0c;透过Web界面的操作&#xff0c;方便快捷操作docker容器化工作。 docker-ui拥有易操作化化界面&#xff0c;不须记忆docker指令&#xff0c;仅需下载镜像即可立刻加入完成部署。基于docker的特性&…

【c++】vector的增删查改

1.先定义一个类对象vector 为了防止和库里面发生冲突&#xff0c;定义一个命名空间&#xff0c;将类对象放在命名空间 里面 #include<iostream> using namespace std; namespace zjw {class vector {public:private:}; }2.定义变量&#xff0c;需要一个迭代器&#xff…

RK3568平台开发系列讲解(存储篇)文件描述符相关系统调用实现

🚀返回专栏总目录 文章目录 一、open 系统调用二、close 系统调用沉淀、分享、成长,让自己和他人都能有所收获!😄 一、open 系统调用 open()系统调用会分配新的文件句柄(file description),用来维护与打开文件相关的元信息(如偏移量、路径、操作方法等),并会给进程…

云计算基础-计算虚拟化-CPU虚拟化

CPU指令系统 在CPU的工作原理中&#xff0c;CPU有不同的指令集&#xff0c;如下图&#xff0c;CPU有4各指令集&#xff1a;Ring0-3&#xff0c;指令集是在服务器上运行的所有命令&#xff0c;最终都会在CPU上执行&#xff0c;但是CPU并不是说所有的命令都是一视同仁的&#xf…