当前位置: 首页>编程语言>正文

python numpy 比较数组 numpy 比较两个数组

一、什么是NumPy

简而言之即包含了许多科学运算的基础包,可以看作在基础的Python上添加了一个用于科学运算的扩展包,这个包里面包含了进行科学运算的一些工具。

python numpy 比较数组 numpy 比较两个数组,python numpy 比较数组 numpy 比较两个数组_数组,第1张

二、ndarray对象

NumPy中核心是ndarray对象,这个对象可以称之为数组,需要注意的是,在Python本身是不存在数组的,只存在列表、元组、字典等元素,但是没有数组,为了运算方便才在NumPy中引入了数组,数组是NumPy中特有的。列表和数组很相似,最大的区别在于列表允许内部元素类型不同,而数组要求内部的数据元素类型必须是一样的,此外,数组在特殊情况下允许数据元素类型不一样,比如内部是长度不同的列表,但是这种方式完全发挥不出来NumPy的优点,所以尽可能不使用。

创建一个ndarray对象可以采用多种方式,主要是两个方向:用已有的列表或者元组进行创建、利用NumPy自带的函数进行创建。

①利用已有的列表或者元组创建。

python numpy 比较数组 numpy 比较两个数组,python numpy 比较数组 numpy 比较两个数组_python_02,第2张

创建之后可以直接查看数组的各项属性。

python numpy 比较数组 numpy 比较两个数组,python numpy 比较数组 numpy 比较两个数组_python_03,第3张

不难发现创建的过程是将list对象的各个属性直接照搬了过来,在维度是二维的情况下还比较容易理解,但是超过二维就比较难想象了。当然也可以利用数组快速生成列表,使用tolist函数即可。

②利用自带函数创建
可以直接使用NumPy里面带的一些方法进行快速生成,常用的方法有:
np.arrange(起点,终点,步长)—根据起点终点步长创建数组
np.linspace(起始值,结束值,元素个数)—创建数组,使用endpoint来控制是否将结束值纳入元素个数内
np.ones([行,列])—生成规定范围的全1数组
np.zeros([行,列])—生成规定范围的全0数组
np.ones_like(数组)—根据数组的形状创建一个全1数组
np.zeros_like(数组)—根据数组的形状创建一个全0数组
np.full([行,列],数值)—根据形状创建一个数组,数组中每个元素的值都为给定的数值
np.full_like(数组,数值)—根据数组的形状创建一个数组,数组中每个元素的值都为给定的数值
np.empty([行,列])—创建一定大小的空数组
np.eye(n)—创建一个n×n大小的单位矩阵
np.diag([数值])—创建一个对角矩阵,对角线上的值为给定的值

创建之后可以利用ndarray对象的属性读取数组的一些特征,一般常用的属性如下:
ndim—秩,即轴的个数
shape—返回数据的维度,对于二维矩阵,返回的是矩阵几行几列
size—数组内部元素的个数
dtype—数组内数据元素的类型
itemsize—每个元素的字节大小

对于已经创建好的数组,可以通过NumPy提供的方法,进行数组的各种变换:

①数组重塑

重塑主要是改变数组的维度,重新调整已有数组的维度,这里主要是用到两个方法:reshape和resize,其中前者重塑数组之后返回一个新的数组,原数组并不发生变化,而后者则会修改原数组中的数据。

python numpy 比较数组 numpy 比较两个数组,python numpy 比较数组 numpy 比较两个数组_numpy_04,第4张

python numpy 比较数组 numpy 比较两个数组,python numpy 比较数组 numpy 比较两个数组_python numpy 比较数组_05,第5张

与上面两个方法相对的是ravel和flatten,这两个方法是展开数组,展开成一维数组,也称为数据散开。

python numpy 比较数组 numpy 比较两个数组,python numpy 比较数组 numpy 比较两个数组_数组_06,第6张

②数组合并

合并指的不是数组的加减,是保留元素的合并,合并主要用到三个方法:hstack(横向合并)、vstack(纵向合并)和concatenate(合并,根据参数axis确定合并的方向)

python numpy 比较数组 numpy 比较两个数组,python numpy 比较数组 numpy 比较两个数组_数组_07,第7张

③数组分割

与数组的合并正好相反,使用hsplit(横向)、vsplit(纵向)和split(利用参数axis指定方向进行分割)进行数组的分割。

三、索引和切片

索引和切片是对数组的常用的两种操作,索引是获取特定位置元素的过程,而切片是获取元素子集的过程。索引和切片本质上是相通的,这是一个从一维推广到高维的过程。索引和数组获得对应下标位置的元素的方法是一个道理,所以没什么重点,但是对于切片需要注意的是,切片得到的是原始数组的视图,不是复制品,也就是说对切片的修改也会导致原始数据的修改,如果想要单独拿出来一个则需要用copy方法,将切片复制一份作为另一个单独的数组。

python numpy 比较数组 numpy 比较两个数组,python numpy 比较数组 numpy 比较两个数组_数据分析_08,第8张

这实际上就是切片的一个使用方法,数组名[开始位置下标:结束位置下标+1],注意结束位置并不是输入的第二个数,而是第二个数的前一个位置,切片后得到的是原数组下标从1到4的四个数。

python numpy 比较数组 numpy 比较两个数组,python numpy 比较数组 numpy 比较两个数组_python numpy 比较数组_09,第9张

这张图则是对视图的解释,将切片的第一个值修改为100,不仅修改了切片的值,原始数据中的切片开始位置的值也发生了修改。但是在切片时搭配copy方法,就可以完全分割开来。

python numpy 比较数组 numpy 比较两个数组,python numpy 比较数组 numpy 比较两个数组_数据分析_10,第10张

对于多维数组的切片相对要麻烦一点,但是主要的思路是不变的,依然是从确定的两个位置开始切。用逗号隔开切片的维度,每个维度用冒号表示切片的起始位置,需要注意起始位置中是不包含结束位置的,下面的多维切片正好对应这一点。

python numpy 比较数组 numpy 比较两个数组,python numpy 比较数组 numpy 比较两个数组_python numpy 比较数组_11,第11张

如图的二维数组切片,切片逗号前面的部分表示的是行的切片范围,0不写,即行上取第一行和第二行,同理,列上取第一列和第二列,最后切出来的就是原二维数组左上角的2X2的数组。本质上还是一维数组切片的一个延伸,每个维度上做切片,最后整合,就是多维数组的切片。对于索引,除了一般的直接索引之外,还有下面几种常用的方法。

①布尔型索引

python numpy 比较数组 numpy 比较两个数组,python numpy 比较数组 numpy 比较两个数组_数组_12,第12张

这种方法是将数组中的元素与目标式子比较,返回一个标记了真假的数组,可以利用这个数组进行筛选。

python numpy 比较数组 numpy 比较两个数组,python numpy 比较数组 numpy 比较两个数组_数据分析_13,第13张

通过name=='Bob’得到了一个标记了真假的数组,当数组值为真时,就将data数组中对应的行输出(这里实际上就是一个where函数)。

②数组索引

python numpy 比较数组 numpy 比较两个数组,python numpy 比较数组 numpy 比较两个数组_python_14,第14张

比较简单的操作,将要筛选的行保存在一个数组里,那么筛选时就会将对应的行筛选出来,同理也可以进行二维的筛选,思路是一样的。下图的二维索引,是将(1,1)和(2,2)位置上的数据拿了出来。

python numpy 比较数组 numpy 比较两个数组,python numpy 比较数组 numpy 比较两个数组_数据分析_15,第15张

四、运算

NumPy很大的一个思想就是让两个数组可以直接像两个数一样进行运算,所以数组的运算可以直接使用加减法,相当于数组中每个对应位置都进行一次相应的运算。

运算分的话可以分为与标量的计算和与数组的运算,与标量的运算就是数组和一个数的运算,等价于数组中每个元素都和这个数做一次运算。与数组的运算也是一个道理,主要有加(+)减(—)乘(*)除(/)幂(**)这五个四则运算,比较运算包括C里面的大小比较,逻辑运算则包括逻辑或、与,返回的是一个布尔值。

数组与数组之间的计算包括下面两种情况:

①同形状的计算

同形状的两个数组进行运算很简单,对应位置上做对应的运算即可。

python numpy 比较数组 numpy 比较两个数组,python numpy 比较数组 numpy 比较两个数组_numpy_16,第16张

②不同形状的运算

另外,对于数组与数组的计算,一个很容易出现的情况就是参与运算的两个数组大小不一样,此时就需要用到广播的原则,广播指的是不同形状的数组之间执行算术运算的方式,广播需要遵循下面的四个原则:

python numpy 比较数组 numpy 比较两个数组,python numpy 比较数组 numpy 比较两个数组_数据分析_17,第17张

形状不同时,会通过广播,将短小的那个数组扩大,扩大到可以运算的大小,使得他们具有兼容的形状。广播的原则为:如果两个数组的后缘纬度(从末尾开始算起的纬度)的轴长度相符或其中一方的长度为1,则认定它们是广播兼容的。简单来说,就是先写出两个数组的形状,倒着看,如果对应位置上数值相等或者其中一个为1,就继续比较下一个,直到某个数组比较完了,如果都符合,则说明这两个数组是符合广播的。

python numpy 比较数组 numpy 比较两个数组,python numpy 比较数组 numpy 比较两个数组_数组_18,第18张

广播后在每个大纬度上进行一次运算。拿上面的图来说,一开始的数据为

python numpy 比较数组 numpy 比较两个数组,python numpy 比较数组 numpy 比较两个数组_数据分析_19,第19张

python numpy 比较数组 numpy 比较两个数组,python numpy 比较数组 numpy 比较两个数组_数组_20,第20张

比较广播规则可知,后面的两个维度是对应的,所以第一个纬度中的每一项都进行一遍运算,当一个轴长度为1,那么先扩大再做运算。arr2为【4】【4】 【4】 【4】,其轴长度为1,所以先扩大为【4 4】 【4 4】 【4 4】 【4 4】,之后再和arr1中的元素对应运算,结果上相当于arr1里面的每个元素加了四。

五、函数

NumPy中提供了大量的函数,方便进行各类的处理,下面简单记录一下一些常用的函数:

①基础函数

基础函数的操作就比较简单了,对应的函数会在每个数组元素上执行一次。

python numpy 比较数组 numpy 比较两个数组,python numpy 比较数组 numpy 比较两个数组_python numpy 比较数组_21,第21张

除此之外还有比较大小用的maximum和minimum,以maximum为例,它会将比较的两个数组中对应位置更大的元素取出来单独存在一个位置上,最后有各位置上最大值组成单独的一个数组。

python numpy 比较数组 numpy 比较两个数组,python numpy 比较数组 numpy 比较两个数组_numpy_22,第22张

常用的一元函数如下:

python numpy 比较数组 numpy 比较两个数组,python numpy 比较数组 numpy 比较两个数组_numpy_23,第23张

python numpy 比较数组 numpy 比较两个数组,python numpy 比较数组 numpy 比较两个数组_python_24,第24张

因为函数特别多,不需要强行记忆,需要时查书也是一个不错的选择。

②统计函数

下面的方法中布尔值也会转换为0和1参与计算。

python numpy 比较数组 numpy 比较两个数组,python numpy 比较数组 numpy 比较两个数组_numpy_25,第25张

python numpy 比较数组 numpy 比较两个数组,python numpy 比较数组 numpy 比较两个数组_python_26,第26张

python numpy 比较数组 numpy 比较两个数组,python numpy 比较数组 numpy 比较两个数组_数组_27,第27张

③where函数

这个函数有三个参数,分别为条件,条件为真时选择值的数组,条件为假时选择值的数组。使用很灵活。

python numpy 比较数组 numpy 比较两个数组,python numpy 比较数组 numpy 比较两个数组_数据分析_28,第28张

④文件读写函数

文件读写如果细分,可以分为读写二进制文件和读写文本文件,二者之间存在一定的区别。读写二进制文件指的是按照NumPy专有的npy后缀的文件进行读写,利用load和save两个函数来进行读写,这种方式虽然写法简单,但是很难用其它语言编写的程序读入。可以理解为一种NumPy专属的快捷读写方式。

python numpy 比较数组 numpy 比较两个数组,python numpy 比较数组 numpy 比较两个数组_数据分析_29,第29张

读取文本文件则主要使用loadtext和savetext两个函数,有时候也可以使用fromfile和tofile。

python numpy 比较数组 numpy 比较两个数组,python numpy 比较数组 numpy 比较两个数组_数据分析_30,第30张

python numpy 比较数组 numpy 比较两个数组,python numpy 比较数组 numpy 比较两个数组_python_31,第31张

需要注意的是,如果读写的是CSV文件,需要调整分隔符,因为CSV文件以逗号作为分隔符的特点,如果读写的形式不对则会出现错误。

python numpy 比较数组 numpy 比较两个数组,python numpy 比较数组 numpy 比较两个数组_python numpy 比较数组_32,第32张

python numpy 比较数组 numpy 比较两个数组,python numpy 比较数组 numpy 比较两个数组_python numpy 比较数组_33,第33张

这后面两个函数存在一些缺点,利用这两个函数进行的读写,会导致数组维度的丢失,如果需要恢复成原来的维度,需要单独保存一下。其实npy文件也存在这个问题,只不过npy文件将维度信息也写进了文件,就不需要单独保存一次。

⑤随机数函数

随机数主要是使用random子库,主要的函数如下:

python numpy 比较数组 numpy 比较两个数组,python numpy 比较数组 numpy 比较两个数组_数组_34,第34张

⑥排序函数

NumPy的排序分为直接排序和间接排序,直接排序是直接对数据进行排序,间接排序则是一个或多个键值对数据集进行排序。

直接排序使用sort函数,参数有四个:

python numpy 比较数组 numpy 比较两个数组,python numpy 比较数组 numpy 比较两个数组_数组_35,第35张

间接排序则使用argsort和lexsort,可以在给定一个或者多个键时,得到一个由整数构成的索引数组,也就是一个由排序后位置组成的数组。

python numpy 比较数组 numpy 比较两个数组,python numpy 比较数组 numpy 比较两个数组_numpy_36,第36张

六、三道作业与图片处理的实例

附作业题目三道,大佬见笑

python numpy 比较数组 numpy 比较两个数组,python numpy 比较数组 numpy 比较两个数组_python numpy 比较数组_37,第37张

import numpy as np
import pandas as pd

arr=np.ones([10,10])
arr2=arr[1:9,1:9]
arr2[arr2==1]=0
print(arr)

arr3=np.random.randint(0,10,(5,2))
print(arr3)
arr4=np.mean(arr3,axis=1)
arr4=arr4.reshape((5,1))
arr3=arr3-arr4
print(arr3)

arr5=np.random.randint(0,1000,(10,10))/10
mmax=arr5.max()
mmin=arr5.min()
for i in range(0, len(arr5)):
    for j in range(0,len(arr5[i])):
        if (arr5[i][j] == mmax):
            arr5[i][j] = 1
        elif (arr5[i][j] == mmin):
            arr5[i][j] = 0
        else:
            arr5[i][j] = arr5[i][j] / (mmax + mmin)
print(arr5)

上面的是大三下学期上课时候的课后题,下面放一下这次重新看Python网课里面的实例程序,这个程序原本是将图片手绘化,本质上就是将图片看作许多的像素,每个像素是一个由三个数组成的列表,利用NumPy中的函数进行处理,就相当于对图片进行了处理。实例代码中包含了很多Image库的内容,所以这部分阅读比较麻烦,而且涉及了一些视角的知识,下面的代码是在给出的源代码基础上又加了一个反色的功能,所以现在程序可以读取一张彩色图片,手绘化之后反色,代码和效果如下:

from PIL import Image
import numpy as np
# 引入需要的库文件,NumPy用于数据处理,Image则用于图片的处理

a = np.asarray(Image.open('C:\Users\Binary\Desktop\leina.jpg').convert('L')).astype('float')
# 打开图片,以黑白形式读取图片,并且转换为浮点数类型

depth = 10. 						# (0-100)
grad = np.gradient(a)				#取图像灰度的梯度值
grad_x, grad_y = grad 				#分别取横纵图像梯度值
grad_x = grad_x*depth/100.
grad_y = grad_y*depth/100.
A = np.sqrt(grad_x**2 + grad_y**2 + 1.)
uni_x = grad_x/A
uni_y = grad_y/A
uni_z = 1./A

vec_el = np.pi/2.2 					# 光源的俯视角度,弧度值
vec_az = np.pi/4. 					# 光源的方位角度,弧度值
dx = np.cos(vec_el)*np.cos(vec_az) 	#光源对x 轴的影响
dy = np.cos(vec_el)*np.sin(vec_az) 	#光源对y 轴的影响
dz = np.sin(vec_el) 				#光源对z 轴的影响

b = 255*(dx*uni_x + dy*uni_y + dz*uni_z) 	#光源归一化
b = b.clip(0,255)

im = Image.fromarray(b.astype('uint8')) 	#重构图像
im.save('C:\Users\Binary\Desktop\leinas.jpg')
# 存储图像

img = np.array(Image.open('C:\Users\Binary\Desktop\leinas.jpg'))
# 再次读取存储的手绘化的图像
imgs = 255 - img
# 反色
im = Image.fromarray(imgs.astype('uint8'))
# 将数组重新组织为图片形式
im.save('C:\Users\Binary\Desktop\leinass.jpg')
# 保存反色后的图片

仅看手绘化的效果如下,祭出刀剑神ED Unlasting的专辑封面:

python numpy 比较数组 numpy 比较两个数组,python numpy 比较数组 numpy 比较两个数组_python_38,第38张

如果再加上反色,效果是下面这样,这里又一次用了蕾娜的萌照:

python numpy 比较数组 numpy 比较两个数组,python numpy 比较数组 numpy 比较两个数组_numpy_39,第39张



https://www.xamrdz.com/lan/5pn1935611.html

相关文章: