Numpy教程——Array
文章目录
一.NumPy简介
1.什么是NumPy?
NumPy是一个用于处理数组的Python库。
它还具有在线性代数、傅里叶变换和矩阵域中工作的函数。
NumPy是特拉维斯·奥列芬特在2005年创建的。它是一个开源项目,可以免费使用。
2.为什么使用NumPy?
在Python中,我们有用于数组的列表,但它们的处理速度很慢。
NumPy的目标是提供一个比传统Python列表快50倍的数组对象。
NumPy中的数组对象称为ndarray
,它提供了许多支持函数,使用ndarray
非常容易。
数组在数据科学中非常常用,在数据科学中速度和资源非常重要。
3.为什么NumPy比Lists更快?
与列表不同,NumPy数组存储在内存中的一个连续位置,因此进程可以非常有效地访问和操作它们。
这种行为在计算机科学中称为局部性原理。
这就是NumPy比列表更快的主要原因。此外,它还进行了优化,以便与最新的CPU架构一起工作。
4.NumPy使用什么语言写的?
NumPy是一个Python库,部分是用Python编写的,但是需要快速计算的大部分是用C或c++编写的。
二.初步使用NumPy
1.导入并使用
import numpy as np
arr = np.array([1, 2, 3, 4, 5])
print(arr)
结果:
2.查看NumPy的版本
版本字符串存储在__version__
属性中。
import numpy as np
print(np.__version__)
结果:
三.NumPy创建数组
1.创建一个NumPyndarray
对象
NumPy被用于处理数组。NumPy中的数组对象被称为ndarray
。
我们通过使用array()
方法创建一个ndarrat
对象。
import numpy as np
arr = np.array([1, 2, 3, 4, 5])
print(arr)
print(type(arr))
结果:
要创建ndarray
,我们可以将list、tuple或任何类似数组的对象传入array()
方法,它将被转换为ndarray
对象:
import numpy as np
arr = np.array((1, 2, 3, 4, 5))
print(arr)
结果:
注意:多个传递进入np.array()
中的参数必须为序列。
若使用arr = np.array( 1, 2, 3, 4, 5 )
则报错。
并且若使用{}
传入set类型序列,则输出一个由{}
所夹的numpy数组:
import numpy as np
arr = np.array( {
1, 2, 3, 4, 5} )
print(arr)
print(type(arr))
结果:
传入List与Tuple的序列,输出都由[]
所夹的numpy数组:
2. numpy数组的维度
嵌套数组:以数组作为元素的数组。
1. 0维数组
0-D数组,或称标量,是数组中的元素。数组中的每个值都是0-D数组。
import numpy as np
arr = np.array(42)
print(arr)
结果:
2. 1维数组
以0-D数组为元素的数组称为一维数组。
这些是最常见和最基本的数组。
import numpy as np
arr = np.array([1, 2, 3, 4, 5])
print(arr)
结果上文已描述
3. 二维数组
以一维数组为元素的数组称为二维数组。
这些常被用来表示矩阵或二阶张量。
NumPy有一个专门用于矩阵操作的完整子模块,称为
NumPy .mat
import numpy as np
arr = np.array([[1, 2, 3], [4, 5, 6]])
print(arr)
结果:
注意:需要保证两个一维数组的维度一致,不然报错。
arr = np.array([[1, 2, 3], [4, 5]])#报错
4.三维数组
以二维数组(矩阵)为元素的数组称为三维数组。
这些常被用来表示一个三阶张量。
import numpy as np
arr = np.array([[[1, 2, 3], [4, 5, 6]], [[1, 2, 3], [4, 5, 6]]])
print(arr)
结果:
5. 查看维度
NumPy Arrays提供了ndim
属性,该属性返回一个整数,告诉我们数组有多少维度。
import numpy as np
a = np.array(42)
b = np.array([1, 2, 3, 4, 5])
c = np.array([[1, 2, 3], [4, 5, 6]])
d = np.array([[[1, 2, 3], [4, 5, 6]], [[1, 2, 3], [4, 5, 6]]])
print(a.ndim)
print(b.ndim)
print(c.ndim)
print(d.ndim)
结果:
6. 高维数组
数组可以有任意维数。
在创建数组时,可以使用ndmin
参数定义维度的数量。
注意区别ndim
与ndmin
。
import numpy as np
arr = np.array([1, 2, 3, 4], ndmin=5)
print(arr)
print('number of dimensions :', arr.ndim)
结果:
维度从低到高:从括号外层到内层
在这个数组的维度(第5维)有4个元素(1,2,3,4),
第4维有1个向量元素,
第3维有1个矩阵元素,
第2维有1个3维数组元素,
第1维有1个4维数组的元素。
四.NumPy数组索引
1.访问(一维)数组元素
NumPy数组中的索引从0开始,这意味着第一个元素的索引为0,第二个元素的索引为1,以此类推。
import numpy as np
arr = np.array([1, 2, 3, 4])
print(arr[2] + arr[3])
结果:
2. 访问二维数组
要访问二维数组中的元素,可以使用逗号分隔的整数表示元素的维数和索引。
可以将二维数组想象成一个具有行和列的表,其中行表示维,索引表示列。
import numpy as np
arr = np.array([[1,2,3,4,5], [6,7,8,9,10]])
print('2nd element on 1st row: ', arr[0, 1])
结果:
3. 访问3维数组
要访问3-D数组中的元素,可以使用逗号分隔的整数表示元素的维数和索引。
import numpy as np
arr = np.array([[[1, 2, 3], [4, 5, 6]], [[7, 8, 9], [10, 11, 12]]])
print(arr[0, 1, 2])
结果:
例子解释:
第一个数字表示第一个维度,它包含两个数组:
[[1,2,3],[4,5,6]]
和
[[7,8,9], [10,11,12]]
因为我们选择了0,所以我们选择了第一个数组:
[[1,2,3], [4,5,6]]
第二个数字表示第二个维度,它也包含两个数组:
[1,2,3]
和
[4,5,6]
因为我们选择了1,所以我们只剩下第二个数组:
[4,5,6]
第三个数字代表第三个维度,它包含三个值:
4
5
6
因为我们选择了2,我们最终得到了第三个值:
6
总结:使用[]
索引从左到右用逗号分隔,即从外往内逐层去掉括号,也即从低维到高维的逐层选择。
4.反向索引
使用负索引从末尾访问数组。
import numpy as np
arr = np.array([[1,2,3,4,5], [6,7,8,9,10]])
print('Last element from 2nd dim: ', arr[1, -1])
结果:
五.NumPy数组切片
1.切片数组
在python中,切片意味着将元素从一个给定索引取到另一个给定索引。
我们可以这样切片数组: [start:end]
。
我们也可以定义步长,像这样:[start:end:step]
。
如果我们不传递start,它就被认为是0
如果我们不传递end,它会直到数组末尾
如果我们不传递步长,它被认为是1
import numpy as np
arr = np.array([1, 2, 3, 4, 5, 6, 7])
print(arr[1:5])
结果:
注意:[start,end]
左闭右开
2. 反向切片
import numpy as np
arr = np.array([1, 2, 3, 4, 5, 6, 7])
print(arr[-3:-1])
结果:
3.设置步长
import numpy as np
arr = np.array([1, 2, 3, 4, 5, 6, 7])
print(arr[::2])
结果:
4. 切片二维数组
import numpy as np
arr = np.array([[1, 2, 3, 4, 5], [6, 7, 8, 9, 10]])
print(arr[1, 1:4])
结果:
import numpy as np
arr = np.array([[1, 2, 3, 4, 5], [6, 7, 8, 9, 10]])
print(arr[0:2, 2])
print(arr[0:2, 1:4])
结果:
六.NumPy数据类型
i
-integerb
-booleanu
-unsigned integerf
-floatc
-complex floatm
-timedeltaM
-datetimeO
-objectS
-stringU
-unicode stringV
-fixed chunk of memory for other type(void)
1.查看Array的数据类型
NumPy数组有一个dtype
的属性,返回数组的数据类型。
import numpy as np
arr1 = np.array([1,2,3,4])
arr2 = np.array(['Hello','python'])
print(arr1.dtype)
print(arr2.dtype)
结果:
2.给定数据类型创建Arrays
import numpy as np
arr = np.array([1, 2, 3, 4], dtype='S')
print(arr)
print(arr.dtype)
结果:
3.若值不能进行类型转换怎么办
如果给定的类型中元素不能进行类型转换,则NumPy将引发ValueError。
import numpy as np
arr = np.array(['a', '2', '3'], dtype='i')
报错
4.对已存在的数组进行类型转换
使用astype()
复制到一个新数组,期间可以传入指定要转换到的类型参数。
import numpy as np
arr = np.array([1.1, 2.1, 3.1])
newarr = arr.astype('i')
# newarr = arr.astype(int) #与上句结果一致
print(newarr)
print(newarr.dtype)
结果:
七.NumPy的拷贝(copy)和视图(view)
1.copy和view的区别
数组的副本和视图之间的主要区别是,副本是一个新数组,而视图只是原始数组的视图。
副本拥有数据,对副本的任何更改都不会影响原始数组,对原始数组的任何更改也不会影响副本。
视图不拥有数据,对视图所做的任何更改都会影响原始数组,而对原始数组所做的任何更改都会影响视图。
- COPY
import numpy as np
arr = np.array([1, 2, 3, 4, 5])
x = arr.copy()
arr[0] = 42
print(arr)
print(x)
结果:
- VIEW
import numpy as np
arr = np.array([1, 2, 3, 4, 5])
x = arr.view()
arr[0] = 42
print(arr)
print(x)
结果:
2.查看数组是否拥有数据
如上述提到的,副本拥有数据,视图没有数据,那怎么去检查一个对象是否有数据呢?
若一个NumPy的数组拥有数据,那么其base
属性会返回None
。
反之,base
属性会引用原始对象。
import numpy as np
arr = np.array([1, 2, 3, 4, 5])
x = arr.copy()
y = arr.view()
print(x.base)
print(y.base)
结果:
八.NumPy数组形状(Shape)
数组的形状是每个维度元素的数量。
1.获取数组形状
NumPy数组有shape
属性,返回一个元组,其中每个索引具有相应元组数量。
import numpy as np
arr = np.array([[1, 2, 3, 4], [5, 6, 7, 8]])
print(arr.shape)
结果:
上面的示例返回(2,4),这意味着数组有2个维度,第一个维度有2个元素,第二个维度有4个。
import numpy as np
arr = np.array([1, 2, 3, 4], ndmin=5)
print(arr)
print('shape of array :', arr.shape)
结果:
2.转换维度(reshape)
- 从一维转化到二维:
import numpy as np
arr = np.array([1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12])
print(arr)
newarr = arr.reshape(4, 3)
print(newarr)
结果:
- 从一维转化到三维
import numpy as np
arr = np.array([1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12])
newarr = arr.reshape(2, 3, 2)
print(newarr)
结果:
可以发现一条规律,一维数组下元素个数等于多维度中各元素个数的乘积。
因此,只要两个形状中需要重新塑造的元素相等,就可以重塑数组到任意形状。
3.重塑数组返回副本(copy)还是视图(view)?
import numpy as np
arr = np.array([1, 2, 3, 4, 5, 6, 7, 8])
print(arr.reshape(2, 4).base)
结果;
可见,返回的是视图(view)。
4.不知道维度怎么去重塑?
可以传入一个”未知“的维度
传入-1
作为值,NumPy将自动计算这个数字。
import numpy as np
arr = np.array([1, 2, 3, 4, 5, 6, 7, 8])
#newarr = arr.reshape(2, -1, 2) #同上句结果
#newarr = arr.reshape(-1, 2, 2) #同上句结果
newarr = arr.reshape(2, 2, -1)
print(newarr)
结果:
注意:不可传入多个-1
,一次reshape()
仅可传入一次 -1
。
5.扁平化(flattening)数组
将数组展平就是将多维数组转换为一维数组。
可以使用reshape(-1)
来做到。
- 从二维转化到一维
import numpy as np
arr = np.array([ [1,2,3],[4,5,6] ])
print(arr)
newarr = arr.reshape(-1)
print(newarr)
结果:
注意:numpy flatten
, ravel
中有很多用于改变数组形状的函数,也可以用于重新排列元素rot90
, flip
, fliplr
, flipud
等。它们属于numpy的中级到高级部分。
九.NumPy数组迭代(Iterating)
迭代意味着逐个遍历元素。
如果我们对n维数组进行迭代,它会一个接一个地遍历n-1维。
1.`对一维数组迭代
简单使用for
:
import numpy as np
arr = np.array([1, 2, 3])
for x in arr:
print(x)
结果:
2.对二维数组(按行)迭代
import numpy as np
arr = np.array([[1, 2, 3], [4, 5, 6]])
for x in arr:
print(x)
结果:
若想对二维数组进行单个元素遍历,则需要双重循环:
import numpy as np
arr = np.array([[1, 2, 3], [4, 5, 6]])
for x in arr:
for y in x:
print(y)
结果:
3.对三维数组迭代
在三维数组中,它会遍历所有的二维数组。
import numpy as np
arr = np.array([[[1, 2, 3], [4, 5, 6]], [[7, 8, 9], [10, 11, 12]]])
for x in arr:
print(x)
结果:
若想返回确切的标量,那么就要进行三重循环:
import numpy as np
arr = np.array([[[1, 2, 3], [4, 5, 6]], [[7, 8, 9], [10, 11, 12]]])
for x in arr:
for y in x:
for z in y:
print(z)
结果:
4.使用nditer()
迭代数组
函数nditer()
是一个帮助函数,从非常基本的迭代到非常高级的迭代都可以使用它。
- 遍历数组中的每一个标量
在基础的for
循环中,若想遍历n维数组的标量,则需要进行n重for
循环,对于高维度的遍历非常困难。而nditer()
可以很好解决这个问题。
import numpy as np
arr = np.array([[[1, 2], [3, 4]], [[5, 6], [7, 8]]])
for x in np.nditer(arr):
print(x)
结果:
5.使用不同的数据类型迭代数组
可以使用op_dtypes
参数,并将预期的数据类型传递给它,以在迭代时更改元素的数据类型。
NumPy不会改变元素的数据类型(元素在数组中的数据类型),因此它需要一些其他空间来执行这个操作,这个额外的空间称为buffer.
为了在nditer()
中启用它,我们传递flags=['buffered']
。
import numpy as np
arr = np.array([1, 2, 3])
for x in np.nditer(arr, flags=['buffered'], op_dtypes=['S']):
print(x)
结果:
6.迭代不同的步长
我们可以使用过滤(filtering)进行迭代。
import numpy as np
arr = np.array([[1, 2, 3, 4], [5, 6, 7, 8]])
for x in np.nditer(arr[:, ::2]):
print(x)
结果:
7.使用ndenumerate()
枚举迭代
枚举是指逐个提出某物的序号。
有时我们在迭代时需要元素的对应索引,ndenumerate()
方法可以用于这些用例。
import numpy as np
arr1 = np.array([1, 2, 3])
arr2 = np.array([[1, 2, 3, 4], [5, 6, 7, 8]])
for idx, x in np.ndenumerate(arr):
print(idx, x)
结果:
十.NumPy连接(Joining)数组
连接意味着将两个或多个数组的内容放在一个数组中。
在SQL中,我们基于键连接表,而在NumPy中,我们通过**轴(axis)**连接数组。
我们将一个想要连接到concatenate()
函数的数组序列连同轴一起传递。如果未显式传递轴,则将其取为0。
1.轴的概念
0轴是行,1轴是列,2轴是纵深。
2.连接数组
- 一维数组合并
import numpy as np
arr1 = np.array([1, 2, 3])
arr2 = np.array([4, 5, 6])
arr = np.concatenate((arr1, arr2))
print(arr)
结果:
- 二维数组合并
import numpy as np
arr1 = np.array([[1, 2], [3, 4]])
arr2 = np.array([[5, 6], [7, 8]])
arr = np.concatenate((arr1, arr2), axis=1)
print(arr)
结果:
3.使用stack()
连接数组
叠加和拼接是一样的,唯一的区别是叠加是沿着一个新的轴进行的。
我们可以沿着第二轴连接两个一维数组这样就可以把它们一个放在另一个上面,叠加。
我们将想要连接到stack()
方法的数组序列与轴一起传递。如果未显式传递axis,则将其取为0。
import numpy as np
arr1 = np.array([1, 2, 3])
arr2 = np.array([4, 5, 6])
arr = np.stack((arr1, arr2), axis=1)
print(arr)
结果:
4.按行叠加
NumPy提供了一个帮助函数:hstack()
来沿行进行叠加。
import numpy as np
arr1 = np.array([1, 2, 3])
arr2 = np.array([4, 5, 6])
arr = np.hstack((arr1, arr2))
print(arr)
结果:
5.按列叠加
NumPy提供了一个帮助函数:vstack()
来沿列进行堆栈。
import numpy as np
arr1 = np.array([1, 2, 3])
arr2 = np.array([4, 5, 6])
arr = np.vstack((arr1, arr2))
print(arr)
结果:
6.按深度(depth)叠加
NumPy提供了一个帮助函数:dstack()
来沿高度进行叠加,高度与深度相同。
十一.NumPy拆分(Splitting)数组
1.拆分一维数组
使用array_split()
来拆分数组,我们传入想要拆分的次数即可。
import numpy as np
arr = np.array([1, 2, 3, 4, 5, 6])
newarr = np.array_split(arr, 3)
print(newarr)
注意:返回值维一个包含三个数组的数组。
如果数组的元素比需要的少,它将从末尾进行相应的调整。
注意:我们也可以使用split()
方法,但它不会在源数组中元素较少时调整元素进行拆分,就像上面的例子一样,array_split()
可以正常工作,但split()
会失败。
2.拆分二维数组
同样使用array_split()
函数。
import numpy as np
arr = np.array([[1, 2], [3, 4], [5, 6], [7, 8], [9, 10], [11, 12]])
newarr = np.array_split(arr, 3)
print(newarr)
结果:
此外,可以指定要围绕哪个轴进行分割,默认为0。
import numpy as np
arr = np.array([[1, 2, 3], [4, 5, 6], [7, 8, 9], [10, 11, 12], [13, 14, 15], [16, 17, 18]])
newarr = np.array_split(arr, 3, axis=1)
print(newarr)
结果:
十二.NumPy数组搜索
1.数组搜索
您可以在数组中搜索某个值,并返回匹配的索引。
要搜索数组,可以使用where()
方法,传入一个逻辑表达式即可。
import numpy as np
arr = np.array([1, 2, 3, 4, 5, 4, 4])
x = np.where(arr == 4)
# x = np.where(arr%2 == 0)
print(x)
结果:
返回一个元组,里面装着一个索引数组,存放元素出现的坐标。
2.数组按序搜索
使用searchsorted()
,传入数组以及想要插入元素。
该方法在数组中执行二进制搜索,并返回将插入指定值在保持搜索顺序情况下的索引。
import numpy as np
arr = np.array([6, 7, 8, 9])
x = np.searchsorted(arr, 7)
print(x)
结果:
若想插入7,则需要在索引’1’的位置。
若想从右侧开始搜索就,只需要添加side='right'
的属性。如x = np.searchsorted(arr, 7, side='right')
也可传入多值:
import numpy as np
arr = np.array([1, 3, 5, 7])
x = np.searchsorted(arr, [2,4,6])
print(x)
结果:
十三.NUmPy数组排序
NumPy的ndarray
对象有sort()
方法,可以将数组排序。
- 一维数组
import numpy as np
arr = np.array([3, 2, 0, 1])
print(np.sort(arr))
结果:
注意:此方法返回数组的副本,保持原数组不变。
- 二维数组
import numpy as np
arr = np.array([[3, 2, 4], [5, 0, 1]])
print(np.sort(arr))
结果:
十四.NumPy过滤器
通常来说,若想选取数组中的部分元素,都要对数组进行迭代,如:
import numpy as np
arr = np.array([41, 42, 43, 44])
filter_arr = []
for element in arr:
if element > 42:
filter_arr.append(True)
else:
filter_arr.append(False)
newarr = arr[filter_arr]
print(filter_arr)
print(newarr)
上面的示例是NumPy中相当常见的任务,NumPy提供了一种很好的方法来处理它。
我们可以直接替换条件中的数组而不是可迭代变量,它将按照我们的预期工作。
import numpy as np
arr = np.array([41, 42, 43, 44])
filter_arr = arr > 42
newarr = arr[filter_arr]
print(filter_arr)
print(newarr)
结果: