首先说一下这篇文章不是NumPy的教程,而是对学习的记录,旨在在以后需要用的时候能够知道What is NumPy。镇上官方NumPy参考手册,这才是系统学习NumPy的真正去处。
约定:
import numpy as np
简介:
NumPy(Numerical Python)是高性能科学计算和数据分析的基础包。NumPy的主要对象是同构数据多维容器(homogeneous multidimensional array)——ndarray,也就是说每一个ndarray都是一个相同类型元素组成的表格(二维)。在NumPy中维度(dimensions)叫做轴(axes),轴的个数叫做秩(rank)。轴这个概念必须牢记,否则放弃吧。首先轴是从0开始计的,0代表最高维,次高维是1,以此类推。
还有两个概念需要认识:
- 面向数组——NumPy本身并没有提供多么高级的数据分析功能,理解NumPy数组以及面向数组的计算将有助于你更加高效地使用诸如pandas之类的工具。
- 矢量化(vectorization)——用数组表达式代替循环的做法。一般来说,矢量化数组运算要比等价的纯Python方式快上一两个数量级(甚至更多),尤其是各种数值计算。
ndarray属性
- ndarray.ndim——ndarray的秩。
- ndarray.shape——书面意思ndarray的形状。官方解释是各维度的大小所组成的tuple元组。
- ndarray.size——数组元素的总个数,等于shape属性中元组元素的乘积。
- ndarray.dtype——是一个特殊的对象,它含有ndarray将一块内存解释为特定数据类型所需的信息。ndarray内部由一个指向数组的指针,一个数据类型,一个表示形状的元组和一个跨度元组(跨越某一维度所需字节数)。由于NumPy关注的是数值计算,所以没有特别指定,dtype基本都是float64(浮点数),果然是基本,
np.arange(10)
产生的数组类型是int32,嗯,推断的还算合理吧。 - ndarray.itemsize——书面意思项大小,就是数组中每一个元素所占字节大小。
- ndarray.data——官方说不需要使用,so 没细研究。
创建ndarray
函数 | 说明 |
---|---|
np.array(data,dtype=None, order=None) | 将数据data(列表、元组、数组或其他序列类型)转换为ndarray。要么推断出dtype,要么显示指定dtype。默认直接复制数据。order默认是A(可能是C可能是F还可能是其它) |
np.asarray(data, dtype=None, order=None) | 将输入数据转换为ndarray,data同上还可以是ndarray,如果是ndarray就不进行复制。dtype同上,order是重塑中行优先C还是列优先F,默认C语言风格。 |
np.arange(10,30,5,dtype=None) | 开始,结束,步长和内置的range相同 |
np.ones( (2,3,4), dtype=None) 、np.ones_like(a) | 根据指定的形状和dtype创建一个全1的数组。ones_like以另一个数组为参数,创建形状和dtype相同的全1数组。 |
np.zeros() 、np.zeros_like() | 全0数组,类似ones和ones_like。 |
np.empty() 、np.empty_like() | 创建数组,只分配内存空间但不填充任何值,所以返回的是垃圾值。类似ones和ones_like。 |
np.eye(N, M=None, k=0, dtype= |
eye创建的是N*M的数组,默认M=N,k取整数,正数对角线向上移k,负数对角线向下移k。identity创建一个N*N单位矩阵(\对角线为1,其余全0)的数组 |
操作
算术运算
大小相等的数组之间的任何算术运算都会将运算应用到元素级。
数组与标量的算术运算也将会将那个标量值传播到各个元素。
当dtype不一致时,采用上溯造型(upcasting)
逻辑运算
<、>、<=、>=、==、!=和&(和)、|(或)、-(非),这些运算符和算术运算符的使用一致,只不过将产生一个新的布尔型数组。
集合运算
NumPy提供了一些针对一维ndarray的基本集合运算。
函数 | 说明 |
---|---|
np.unique(x, return_counts=False) | 计算x中的唯一元素,并返回有序数组, return_counts=True时一并返回对应元素的数量数组。 |
np.intersect1d(x,y) | (交)计算x,y中的公共元素,并返回有序数组 |
np.union1d(x,y) | (并)计算x,y的并集,并返回有序数组 |
np.in1d(x,y) | (包含)得到一个表示x的元素是否包含于y的布尔型数组 |
np.setdiff1d(x,y) | (差)集合的差,即元素在x中且不在y中 |
np.setxor1d(x,y) | (异或)集合的对称差,即存在于一个数组中但不同时存在于两个数组中的元素。 |
索引
索引这一节一句半句说不清,另起一篇来写。
形状操纵
reshape(x,y,...)返回修改的新数组,resize((x,y,...))返回修改后的自身。
转置:
转置(transpose)是重塑的一种特殊形式它返回的是源数据的视图。数组不仅有transpose方法,还有一个特殊的T属性。简单的转置可以使用.T
,他其实就是进行轴对换而已。ndarray还有一个swapaxes方法,他需要接受一对轴编号eg:swapaxes(0,1)。对于高维数组transpose需要一个轴编号组成的元组才能对这些轴进行转置。
这里对transpose解释一下
In [4]: arr = np.arange(16).reshape((2,2,4))
In [5]: arr
Out[5]:
array([[[ 0, 1, 2, 3],
[ 4, 5, 6, 7]],
[[ 8, 9, 10, 11],
[12, 13, 14, 15]]])
In [6]: arr.transpose((1,0,2))
Out[6]:
array([[[ 0, 1, 2, 3],
[ 8, 9, 10, 11]],
[[ 4, 5, 6, 7],
[12, 13, 14, 15]]])
简而言之就是将原来的0,1,2轴变成现在的1,0,2,转换后的0轴是原来的1轴,转换后的1轴是原来的0轴,2轴未变。
换种解释:比如说8元素的索引是[1,0,0],0,1轴变换后是[0,1,0]。
组合不同的数组(堆stack):
hstack
, vstack
, column_stack
, concatenate
, c_
, r_
其他
用于数组的文件输入输出
NumPy能够读写磁盘上的文本数据或二进制数据。
np.save和np.load是读写磁盘数组数据的两个主要函数。默认情况下,数据是以未压缩的原始二进制格式保存在扩展名为.npy的文件中的。如果文件路径末尾没有扩展名.npy,则该扩展名会被自动加上。通过np.savez可以将多个数组保存到一个压缩文件中,将数组以关键字参数的形式传入即可np.savez('array_archive.npz',a=arr1, b=arr2)
,加载.npz文件时,你会得到一个类似字典的对象,该对象会对各个数组进行延迟加载。
NumPy提供了从文件中加载文本的函数np.loadtxt(),还有更为专门化的np.genfromtxt()将数据加载到普通的NumPy数组中,只不过他面向的是结构化数组和缺失数据处理。这些函数都许多选项可供使用:指定各种分隔符、针对特定列的转换器函数、需要跳过的行数等。完整版的np.loadtxt(fname, dtype=
,注解默认‘#’,分隔符默认whitespace空白,converters = dict{columu : function}。np.savetxt()执行的是相反的操作。
复制和视图
简单的赋值不拷贝数组对象或者他们的数据;视图就是同一数据的引用,改视图,就是改数据;切片返回的是视图。显示复制用copy()函数。其实考虑一下NumPy工具出现的目的也能明白,能够高效、快速处理大量数据,老是复制多费劲,还占内存。
如有理解不正确之处或者解释不通的地方,欢迎指正,共同进步,有时候个人的理解并不能解释忽略的、更高层面情况。