转自:DawnRanger的专栏
https://blog.csdn.net/DawnRanger/article/details/53125945
Numeric Python的简称,是几乎所有python科学计算工具的基础。主要功能:
- ndarray: 一个具有矢量运算和复杂广播能力的快速并且节省空间的多维数组
- 面向数组的运算: 对于数组进行快速运算的标准数学函数
- 磁盘读写、内存映射
- 线性代数、随机数、傅里叶变换
NumPy本身并没有提供什么高级的数据分析能力,但是理解NumPy数组以及面向数组的计算将有利于使用pandas等工具。
2. ndarray:一种多维数组对象
ndarray是一个通用的同构数据多维容器,其中的所有元素必须是相同类型的。ndarray含有两个属性:
shape
: 一个表示各维度大小的数组dtype
:一个用于说明数据类型的对象
2.1 创建ndaray
1) array函数
它接受一切序列型的对象(list/set/tuple/ndarray/…)。除非显式说明,np.array会尝试为新建的这个数组推断出一个较为合适的数据类型:
import numpy as np
arr1 = np.array([1,2,3,4,5])
arr2 = np.array([[1,2,3,4], [5,6,7,8]]) # 二维数组
- 1
- 2
- 3
- 4
2) zeros/ones/empty函数
创建指定长度或形状的全0或全1或空数组,只需传入一个表示形状的元组(tuple)即可:
np.zeros(10)
np.ones((3,6)
np.empty((2,3,2)) #注意返回的并不是全0数组,而是未初始化的随机值
- 1
- 2
- 3
- 4
3) linspace函数:linspace(start, stop, num=50, endpoint=True, retstep=False, dtype=None)
返回在start到stop之间均匀分布的num个数字,可以选择是否包括stop. retstep表示是否返回步长.
np.linspace(1,5,5,True)
Out[4]: array([ 1., 2., 3., 4., 5.])
np.linspace(1,5,5,False)
Out[5]: array([ 1. , 1.8, 2.6, 3.4, 4.2])
- 1
- 2
- 3
- 4
- 5
- 6
3) arange函数:arange([start,] stop[, step,], dtype=None)
python内置函数range的数组版
np.arange(15)
- 1
- 2
4) 其它函数:
由于NumPy关注的是数值计算,因此,如果没有特别指定,数据类型基本都是float64(浮点数)
array
将输入转换为ndarray,默认直接复制输入数据asarray
将输入转换为ndarray,如果输入本身就是一个ndarray就不进行复制ones_like
/zeros_like
/empty_like
以另一个数组为参数,并根据其形状和dtype创建一个全0/全1/空数组eye
/identify
创建一个N×N” role=”presentation”>N×NN×N单位矩阵(对角线为1,其余为0)
2.2 ndaray的数据类型
dtype含有ndarray将一块内存解释为特定数据类型所需要的信息
arr1 = np.array([1,2,3], dtype = np.float64)
arr2 = np.array([1,2,3], dtype = np.int32)
arr2 = np.array([1,2,3], dtype = 'i4') # 也可以写类型代码
arr1.dtype
Out[5]: dtype('float64')
arr2.dtype
Out[6]: dtype('int32')
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
NumPy的数据类型:
int8
/int16
/int32
/int64
有符号8/16/32/64位整数,类型代码 i1/i2/i4/i8 (分别为1/2/4/8个字节)uint8
/uint16
/uint32
/uint64
无符号8/16/32/64位整数,类型代码 u1/u2/u4/u8float16
/float32
/float64
/float128
浮点数,类型代码 f2/f4/f8/f16complex64
/complex128
/complex256
复数,类型代码 c8/c16/c32bool
布尔类型 ,类型代码 ?object
Python对象类型,类型代码 Ostring_
固定长度的字符串类型(每个字符一个字节),类型代码 S 。例如,要创建一个长度为10的字符串,应使用S10unicode
固定长度的unicode类型,类型代码 U 。同字符串(如U10)
数据类型转换: astype方法
int_arr = np.array([1,2,3,4,5])
float_arr = int_arr.astype(np.float64)
numeric_str = np.array (['1.25', '-9.6', '42'], dtype = np.string_)
float_arr = numeric_str.astype(float) # 这里的float是Python的数据类型,NumPy会自动的将其映射到等价的dtype上,即np.float64
- 1
- 2
- 3
- 4
- 5
- 6
注意:astype无论如何都会创建出一个新的数组(原始数据的一分拷贝)
2.3 ndaray与标量的计算
使用数组运算的好处是不写循环即可对数据进行批量运算,即矢量化(vectorization)。需要注意的是:
- 大小相等的数组之间的任何算术运算都会将运算应用到元素级
- 数组与标量的算术运算会将标量值传播到各个元素
不同大小的数组之间的运算叫做广播(broadcasting)。
2.4 索引与切片
2.4.1 一维数组
一维数组的索引与切片和Python列表的功能类似,区别在于,数组切片是原始数组的视图,这意味着数据不会被复制,对视图的任何修改都会直接反映到原数组上。NumPy如此设计的目的是为了处理大数据,如果采取复制的方法可能产生性能和内存的问题。
arr = np.arange(10)
arr[5:8] = 12
arr
Out[10]:array([0, 1, 2, 3, 4, 12, 12, 12, 8, 9])
- 1
- 2
- 3
- 4
- 5
如果一定要复制可以使用copy方法显式的复制。
2.4.2 多维数组
多维数组中,如果省略了后面的索引,则返回对象会是一个维度低一点的ndarray。例如,二维数组中,各索引位置上的元素不再是标量而是一维数组。
arr2d = np.array([[1,2,3], [4,5,6], [7,8,9]])
arr2d[2]
Out[11]:array([7, 8, 9])
arr2d[0][2]
arr2d[0,2] # 这两种索引方法等价
- 1
- 2
- 3
- 4
- 5
- 6
2.4.3 多维数组切片
多维数组切片与一维数组稍有不同
arr2d = np.array([[1,2,3], [4,5,6], [7,8,9]])
arr2d[:2]
Out[1]: array([[1,2,3],
[4,5,6]])
- 1
- 2
- 3
- 4
- 5
可以看出,它是按第0轴(第一个轴)切片的。切片是沿着一个轴向选取元素的。
可以一次传入多个切片,也可以将整数索引和切片混合:
arr2d[:2, 1:]
Out[2]: aray([[2,3],
[5,6])
arr2d[1, :2]
Out[3]: array([4, 5])
arr2d[:, :1]
Out[4]: aray([[1],
[4],
[7]])
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
2.4.4 布尔型索引
与算数运算类似,数组的比较运算(如==)也是矢量化的。
names = np.array(['Bob', 'Joe', 'Will', 'Bob', 'Will', 'Joe', 'Joe'])
data = np.random.randn(7, 4) # 产生7x4的随机数组
names == 'Bob'
Out[5]: array([True, False, False, True, False, False, False], dtype = bool)
data[names == 'Bob'] # 布尔索引
data[names = 'Bob', 2:] # 布尔索引与切片
data[-(names == 'Bob')]
mask = (names == 'Bob') | (names = 'Will') # 多个布尔条件用&(与)、|(或)等连接起来。(and/or无效)
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
通过布尔型索引选取数组中的数据,将总是创建副本,即使返回一模一样的数组。通过布尔型数组设置值是常用的手段。例如:
data[data<0] = 0 # 将data中的所有的负值都设为0
data[names != 'Joe'] = 7 # 将不为Joe的值设为7
- 1
- 2
- 3
2.4.5 花式索引(Fancy indexing)
利用整数数组进行索引。
正常情况下的索引:
In [17]: arr = np.empty((8,4))
In [18]: for i in range(8):
...: arr[i] = i # 矢量化赋值
In [19]: arr
Out[19]:
array([[ 0., 0., 0., 0.],
[ 1., 1., 1., 1.],
[ 2., 2., 2., 2.],
[ 3., 3., 3., 3.],
[ 4., 4., 4., 4.],
[ 5., 5., 5., 5.],
[ 6., 6., 6., 6.],
[ 7., 7., 7., 7.]])
In [23]: arr[[4,3,0,6]] # 选取多行,注意要加括号[]
Out[23]:
array([[ 4., 4., 4., 4.],
[ 3., 3., 3., 3.],
[ 0., 0., 0., 0.],
[ 6., 6., 6., 6.]])
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
一次传入多个索引数组时,它返回的是一个一维数组,其中的元素对应各个索引元组。
In [24]: arr = np.arange(32).reshape((8,4))
In [25]: arr
Out[25]:
array([[ 0, 1, 2, 3],
[ 4, 5, 6, 7],
[ 8, 9, 10, 11],
[12, 13, 14, 15],
[16, 17, 18, 19],
[20, 21, 22, 23],
[24, 25, 26, 27],
[28, 29, 30, 31]])
In [26]: arr[[1,5,7,2], [0,2,1,3]]
Out[26]: array([ 4, 22, 29, 11])
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
最终选出的元素是(1, 0)、(5, 3)、(7, 1)、(2, 2)。
如果想要选取数组的行列子集,可以采用以下方法:
In [33]: arr[[1,5,7,2]][:,[0,3,1,2]] # 可以把左右两个[]分开来理解
Out[33]:
array([[ 4, 7, 5, 6],
[20, 23, 21, 22],
[28, 31, 29, 30],
[ 8, 11, 9, 10]])
- 1
- 2
- 3
- 4
- 5
- 6
- 7
另一种方法是使用 np.ix_ 函数,它可以将两个一维整数数组转换为一个用于选取方形区域的索引器:
In [34]: arr[np.ix_([1,5,7,2],[0,3,1,2])]
Out[34]:
array([[ 4, 7, 5, 6],
[20, 23, 21, 22],
[28, 31, 29, 30],
[ 8, 11, 9, 10]])
- 1
- 2
- 3
- 4
- 5
- 6
- 7
与切片不同,花式索引总是将数据复制到新数组中。
2.5 数组转置和轴变换
返回原数据的视图,不会进行任何复制。数组有transpose/swapaxes方法和T属性。
3. numpy通用函数
一元函数:
abs/fabs
绝对值。对于非复数,可以使用更快的fabssqrt/square/exp/log/log10/log2/log1p
平方根/平方/指数/自然对数/底数为10的log/底数为2的logsign
返回元素的符号:1(正数)、0(零)、-1(负数)ceil/floor
取上界/下界整数rint
四舍五入到整数modf
返回数组的小数和正数两个独立的数组isnan
返回布尔数组,判断是否为数字isfinite/isinf
是否有穷/无穷cos/cosh/sin/sinh/tan/tanh
普通和双曲三角函数
二元函数:
add/subtract/multiply/divide/floor_divide
加/减/乘/除/向下圆整除法power
第一个数组中的是底数,第二个数组中的是指数maximum/fmax/minimum/fmin
最大最小值(fmax/fmin忽略NaN)mod
取模copysign
将第二个数组中的值的符号复制给第一个数组中greater/greater_equal/less/less_equal
元素级比较,产生布尔数组。logical_and/logical_or/logical_xor
元素级真值逻辑运算。&、|、^。
4. 利用数组进行数据处理
一般来说矢量化数组运算要比等价的纯Python方式快上一两个数量级,尤其是各种数值计算。广播是一种针对矢量化计算的强大手段。
4.1 将条件逻辑表述为数组运算
numpy.where
函数是三元表达式 x if condition else y
的矢量化版本:where(condition, [x, y])
arr = randn(4,4)
np.where(arr>0, 2, -2) # 争执设置为2,负值设置为-2
np.where(arr>0, 2, arr) # 只讲正值设置为2
- 1
- 2
- 3
- 4
条件是可以嵌套的:
np.where(cond1 & cond2, 0,
np.where(cond1, 1,
np.where(cond2, 2, 3)))
- 1
- 2
- 3
- 4
4.2 数学和统计方法
聚合计算(aggregation):既能当数组的实例方法调用,也可以当做顶级NumPy函数使用;可接受一个 axis 参数
- sum
/mean
/std
/var
/min
/max
/argmin
/argmax
求和,平均数,标准差,方差,最大值,最小值,最大最小元素的索引
不聚合,产生一个由中间结果组成的数组:
- cumsum
、cumprod
所有元素的累积和/累计积
4.3 用于布尔型数组的方法
bools = np.array([False, False, True, False])
(bools>0).sum() # 正值的数量
bools.any() # 测试数组中是否存在一个或多个True
bools.all() # 检查数组中所有值是否都是True
- 1
- 2
- 3
- 4
- 5
4.4 排序
Numpy数组自带sort方法,如果需要在某一个轴向上进行排序,只需要将轴编号传递给sort.
顶级方法np.sort返回的是数组已排序的副本,而数组自带sort方法则会直接修改数组本身.
arr = randn(5, 3)
arr.sort(1)
large_arr = randn(1000)
large_arr.sort()
large_arr[int(0.05 * len(large_arr))] # 5%分位数
- 1
- 2
- 3
- 4
- 5
- 6
4.5 唯一化以及其它的集合逻辑
集合运算函数:
unique(x)
返回唯一元素intersect1d(x,y)
交集union1d(x,y)
并集in1d(x,y)
布尔型数组,表示x中的元素是否存在于y中setdiff1d(x,y)
差setxor1d(x,y)
异或
5. 用于数组的文件操作
二进制文件: np.save
、 np.load
文本文件: np.loadtxt
、 np.savetxt
6. 线性代数
常用numpy.linalg函数
dot
矩阵乘法。两个一维数组计算点乘,两个多维数组计算叉乘diag
返回矩阵对角线元素trace
对角线元素和det
行列式eig
特征值、特征向量inv
逆qr
QR分解svd
奇异值分解solve
解线性方程Ax=blstsq
计算Ax=b的最小二乘解
7. 随机数生成
生成随机数的方法:
rand
均匀分布的样本值randint
给定上下限的随机整数randn
标准正态分布binomial
二项分布normal
正态分布chisquare
卡方分布gamma
Gamma分布uniform
[0,1]之间的均匀分布