数组对象的属性
size
属性:数组元素
代码:
array19 = np.arange(1, 100, 2)
array20 = np.random.rand(3, 4)
print(array19.size, array20.size)
输出:
50 12
shape
属性:数组的形状
代码:
print(array19.shape, array20.shape)
输出:
(50,) (3, 4)
dtype
属性:数组元素的数据类型
代码:
print(array19.dtype, array20.dtype)
输出:
int64 float64
ndarray
对象元素的数据类型可以参考如下所示的表格。
![e05031d6a440be251e2f669dfb945961.png](https://i-blog.csdnimg.cn/blog_migrate/fc5ef09ae1690e96096d54b3078b6a65.jpeg)
ndim
属性:数组的维度
代码:
print(array19.ndim, array20.ndim)
输出:
1 2
itemsize
属性:数组单个元素占用内存空间的字节数
代码:
array21 = np.arange(1, 100, 2, dtype=np.int8)
print(array19.itemsize, array20.itemsize, array21.itemsize)
输出:
8 8 1
说明:在使用arange
创建数组对象时,通过dtype
参数指定元素的数据类型。可以看出,np.int8
代表的是8位有符号整数,只占用1个字节的内存空间,取值范围是。
nbytes
属性:数组所有元素占用内存空间的字节数
代码:
print(array19.nbytes, array20.nbytes, array21.nbytes)
输出:
400 96 50
flat
属性:数组(一维化之后)元素的迭代器
代码:
from typing import Iterable
print(isinstance(array20.flat, np.ndarray), isinstance(array20.flat, Iterable))
输出:
False True
base
属性:数组的基对象(如果数组共享了其他数组的内存空间)
代码:
array22 = array19[:]
print(array22.base is array19, array22.base is array21)
输出:
True False
说明: 上面的代码用到了数组的切片操作,它类似于Python中list
类型的切片,但在细节上又不完全相同,下面会专门讲解这个知识点。通过上面的代码可以发现,ndarray
切片后得到的新的数组对象跟原来的数组对象共享了内存中的数据,因此array22
的base
属性就是array19
对应的数组对象。
数组的索引和切片
和Python中的列表类似,NumPy的ndarray
对象可以进行索引和切片操作,通过索引可以获取或修改数组中的元素,通过切片可以取出数组的一部分。
- 索引运算(普通索引)
代码:
array23 = np.array([1, 2, 3, 4, 5, 6, 7, 8, 9])
print(array23[0], array23[array23.size - 1])
print(array23[-array23.size], array23[-1])
输出:
1 9
1 9
代码:
array24 = np.array([[1, 2, 3], [4, 5, 6], [7, 8, 9]])
print(array24[2])
print(array24[0][0], array24[-1][-1])
print(array24[1][1], array24[1, 1])
输出:
[7 8 9]
1 9
5 5
代码:
array24[1][1] = 10
print(array24)
array24[1] = [10, 11, 12]
print(array24)
输出:
[[ 1 2 3]
[ 4 10 6]
[ 7 8 9]]
[[ 1 2 3]
[10 11 12]
[ 7 8 9]]
- 切片运算(切片索引)
切片是形如[开始索引:结束索引:步长]
的语法,通过指定开始索引(默认值无穷小)、结束索引(默认值无穷大)和步长(默认值1),从数组中取出指定部分的元素并构成新的数组。因为开始索引、结束索引和步长都有默认值,所以它们都可以省略,如果不指定步长,第二个冒号也可以省略。一维数组的切片运算跟Python中的list
类型的切片非常类似,此处不再赘述,二维数组的切片可以参考下面的代码,相信非常容易理解。
代码:
print(array24[:2, 1:])
输出:
[[2 3]
[5 6]]
代码:
print(array24[2])
print(array24[2, :])
输出:
[7 8 9]
[7 8 9]
代码:
print(array24[2:, :])
输出:
[[7 8 9]]
代码:
print(array24[:, :2])
输出:
[[1 2]
[4 5]
[7 8]]
代码:
print(array24[1, :2])
print(array24[1:2, :2])
输出:
[4 5]
[[4 5]]
代码:
print(array24[::2, ::2])
输出:
[[1 3]
[7 9]]
代码:
print(array24[::-2, ::-2])
输出:
[[9 7]
[3 1]]
关于数组的索引和切片运算,大家可以通过下面的两张图来增强印象,这两张图来自《利用Python进行数据分析》一书,它是pandas的作者Wes McKinney撰写的Python数据分析领域的经典教科书,有兴趣的读者可以购买和阅读原书。
![90365658da8546cfad8c84c83b64a52e.png](https://i-blog.csdnimg.cn/blog_migrate/f90cd92d76196c2b853718f03db964df.jpeg)
![f236f3af227a9dc24175811814e62fd9.png](https://i-blog.csdnimg.cn/blog_migrate/5d7b47726e3df413b42dd0106e5c9b1e.jpeg)
- 花式索引(fancy index)- 利用整数数组进行索引,这里所说的整数数组可以是NumPy的
ndarray
,也可以是Python中list
、tuple
等可迭代类型,可以使用正向或负向索引。
代码:
array25 = np.array([50, 30, 15, 20, 40])
array25[[0, 1, -1]]
输出:
array([50, 30, 40])
代码:
array26 = np.array([[30, 20, 10], [40, 60, 50], [10, 90, 80]])
# 取二维数组的第1行和第3行
array26[[0, 2]]
输出:
array([[30, 20, 10],
[10, 90, 80]])
代码:
# 取二维数组第1行第2列,第3行第3列的两个元素
array26[[0, 2], [1, 2]]
输出:
array([20, 80])
代码:
# 取二维数组第1行第2列,第3行第2列的两个元素
array26[[0, 2], 1]
输出:
array([20, 90])
- 布尔索引 - 通过布尔类型的数组对数组元素进行索引,布尔类型的数组可以手动构造,也可以通过关系运算来产生布尔类型的数组。
代码:
array27 = np.arange(1, 10)
array27[[True, False, True, True, False, False, False, False, True]]
输出:
array([1, 3, 4, 9])
代码:
array27 >= 5
输出:
array([False, False, False, False, True, True, True, True, True])
代码:
array27[array27 >= 5]
输出:
array([5, 6, 7, 8, 9])
提示:切片操作虽然创建了新的数组对象,但是新数组和原数组共享了数组中的数据,简单的说,如果通过新数组对象或原数组对象修改数组中的数据,其实修改的是同一块数据。花式索引和布尔索引也会创建新的数组对象,而且新数组复制了原数组的元素,新数组和原数组并不是共享数据的关系,这一点通过前面讲的数组的
base
属性也可以了解到,大家一定要注意。
案例:通过数组切片处理图像
学习基础知识总是比较枯燥且没有成就感的,所以我们还是来个案例为大家演示下上面学习的数组索引和切片操作到底有什么用。前面我们说到过,可以用三维数组来表示图像,那么通过图像对应的三维数组进行操作,就可以实现对图像的处理,如下所示。
读入图片创建三维数组对象。
guido_image = plt.imread('guido.jpg')
plt.imshow(guido_image)
对数组的0轴进行反向切片,实现图像的垂直翻转。
plt.imshow(guido_image[::-1])
![f5c77e14cba8c6b59616b0261dfd7ad9.png](https://i-blog.csdnimg.cn/blog_migrate/cd032f88abd7606187209c750c28fe1d.jpeg)
对数组的1轴进行反向切片,实现图像的水平翻转。
plt.imshow(guido_image[:,::-1])
![5b24136d3bc8f98856340e98898eb1e7.png](https://i-blog.csdnimg.cn/blog_migrate/a4e227837c4574f91cba817ceef94550.jpeg)
将Guido的头切出来。
plt.imshow(guido_image[30:350, 90:300])
![aa2fb55e513544ba13763a29fd1c7da2.png](https://i-blog.csdnimg.cn/blog_migrate/cb5bc220360969c6083c697c0d34b52c.jpeg)
数组对象的方法
统计方法
ndarray
对象的统计方法主要包括:sum
、mean
、std
、var
、min
、max
、argmin
、argmax
、cumsum
等,分别用于对数组中的元素求和、求平均、求标准差、求方差、找最大、找最小、求累积和等,请参考下面的代码。
array28 = np.array([1, 2, 3, 4, 5, 5, 4, 3, 2, 1])
print(array28.sum())
print(array28.mean())
print(array28.max())
print(array28.min())
print(array28.std())
print(array28.var())
print(array28.cumsum())
输出:
30
3.0
5
1
1.4142135623730951
2.0
[ 1 3 6 10 15 20 24 27 29 30]
其他方法
all()
/any()
方法:判断数组是否所有元素都是True
/ 判断数组是否有为True
的元素。astype()
方法:拷贝数组,并将数组中的元素转换为指定的类型dot()
方法:实现一个数组和另一个数组的点积运算。在数学上,点积(dot product)又称数量积或标量积,是一种接受两个等长的数字序列,返回单个数字的代数运算。从代数角度看,先对两个数字序列中的每组对应元素求积,再对所有积求和,结果即为点积,即:。从几何角度看,点积则是两个向量的长度与它们夹角余弦的积,即:
。在欧几里得几何中,两个笛卡尔坐标向量的点积也称为
的特例,而内积可以推广到
代码:
array29 = np.array([3, 4])
array30 = np.array([5, 6])
array29.dot(array30)
输出:
39
代码:
array31 = np.array([[1, 2, 3], [4, 5, 6]])
array32 = np.array([[1, 2], [3, 4], [5, 6]])
array31.dot(array32)
输出:
array([[22, 28],
[49, 64]])
说明:可以看出,二维数组的点积就是矩阵乘法运算。
dump()
方法:保存数组到文件中,可以通过NumPy中的load
函数从保存的文件中加载数据创建数组。
代码:
array31.dump('array31-data')
array32 = np.load('array31-data', allow_pickle=True)
array32
输出:
array([[1, 2],
[3, 4],
[5, 6]])
fill()
方法:向数组中填充指定的元素。flatten()
方法:将多维数组扁平化为一维数组。
代码:
array32.flatten()
输出:
array([1, 2, 3, 4, 5, 6])
nonzero()
方法:返回非0元素的索引。round()
方法:对数组中的元素做四舍五入操作。sort()
方法:对数组进行就地排序。
代码:
array33 = np.array([35, 96, 12, 78, 66, 54, 40, 82])
array33.sort()
array33
输出:
array([12, 35, 40, 54, 66, 78, 82, 96])
swapaxes()
和transpose()
方法:交换数组指定的轴。
代码:
# 指定需要交换的两个轴,参数顺序无所谓
array32.swapaxes(0, 1)
输出:
array([[1, 3, 5],
[2, 4, 6]])
代码:
# 对于二维数组,transpose相当于实现了矩阵的转置
array32.transpose()
输出:
array([[1, 3, 5],
[2, 4, 6]])
take()
方法:从数组中取指定索引的元素,类似于花式索引。
代码:
array34 = array33.take([0, 2, -3, -1])
array34
输出:
array([12, 40, 78, 96])
tolist()
方法:将数组转成Python中的list
。