Numpy库基础
一. 基本介绍
Numpy( Numerical Python)是python中的高性能科学计算与分析的基础包,这个库可以说是数据科学的基础,也是后面学习Pandas所需的基础。它的主要功能其实并不包含数据分析,只是它是面向数组的,可以以高性能且节省空间的多维数组进行复杂的矢量计算或线性代数计算,而且无需编写循环,同时还能用于集成C/C++编写的代码。
二.ndarray数组对象
1. 基本介绍:ndarray是一种快速而灵活的大数据容器,是整个numpy库的基础。
2. 构造的基本方法( 以下代码都是在from numpy import * 基础上):
- 最简单的,用一个列表构造:
In [3]: data = array([1, 2, 3, 4])
In [4]: data
Out[4]: array([1, 2, 3, 4])
#多维嵌套
In [5]: data = array([[1, 2, 3, 4], [5, 6, 7, 8]])
In [6]: data
Out[6]:
array([[1, 2, 3, 4],
[5, 6, 7, 8]])
- 利用arange() 与asarray()函数构造 :
#使用arange(arg)函数,构造0-arg数组
In [7]: data = array(arange(6))
In [8]: data
Out[8]: array([0, 1, 2, 3, 4, 5])
#使用asarray(arg)函数,将arg转化为数组
In [12]: data = array(asarray('abcd'))
In [13]: data
Out[13]: array('abcd', dtype='<U4')
- 使用0或1填充
#ones(arg)或者zeros(arg)为用arg个1或0填充数组
In [20]: data = ones(3)
In [21]: data
Out[21]: array([1., 1., 1.])
#注意要传数组维度大小要用括号括起来
In [22]: data = ones((3, 3))
In [23]: data
Out[23]:
array([[1., 1., 1.],
[1., 1., 1.],
[1., 1., 1.]])
#ones_like或者zeros_like(array)则是用1或者0填充大小维度与data一样的数组
In [24]: data1 = ones_like(data)
In [25]: data1
Out[25]:
array([[1., 1., 1.],
[1., 1., 1.],
[1., 1., 1.]])
#empty()与empty_like()则类比上面的,返回一个未初始化的数组
In [26]: data2 = empty(4)
In [27]: data2
Out[27]: array([4.67587575e-310, 6.94143033e-310, 4.94065646e-324, nan])
In [28]: data2 = empty_like(data1)
In [29]: data2
Out[29]:
array([[1., 1., 1.],
[1., 1., 1.],
[1., 1., 1.]])
3.数组中的数据类型
1.数组对象的数据类型存储在数组的dtype属性中可以通过.dtype访问
2.下面是Numpy数据类型表:
类型 | 类型代码 | 说明 |
---|---|---|
int8, unit8 | i1, u1 | 8位有符号与无符号整型 |
int16, uint16 | i2, u2 | 16位有符号与无符号整型 |
int32, uint32 | i3, u3 | 32位有符号与无符号整型 |
int64, uint64 | i4, u4 | 64位有符号与无符号整型 |
float16 | f2 | 半精度浮点数 |
float32 | f4或者f | 标准单精度浮点数,与C的float兼容 |
float64 | f8或者d | 标准的双精度浮点数,与C的double兼容 |
float128 | f16或者g | 拓展精度浮点数 |
complex64, complex128,complex256 | c8,c16, c32 | 分别用两个32位,64位,128位浮点数表示的复数 |
bool | ? | 存储True或者False的布尔值 |
object | O | python对象类型 |
string_ | Sn | 固定长度的字符串类型(每个字符1字节)如长度为10要用S10 |
unicode_ | Un | 固定长度的Unicode类型(字节长度由平台决定),如长度为10要用U10 |
- 数据类型转换astype():
In [38]: data.dtype
Out[38]: dtype('float64')
In [39]: int_data = data.astype(int8)
In [40]: int_data
Out[40]:
array([[1, 1, 1],
[1, 1, 1],
[1, 1, 1]], dtype=int8)
- 在初始化数组的时候可以显式指定数据类型
In [42]: data = ones(10, dtype=int8)
In [43]: data
Out[43]: array([1, 1, 1, 1, 1, 1, 1, 1, 1, 1], dtype=int8)
4.数组运算
- 数组与标量间的运算:数组中的广播机制使得我们不用编写循环便可以对每个元素进行操作
In [44]: data1 = array([[1, 2, 3,4],[4, 5, 6, 7]])
In [45]: data1
Out[45]:
array([[1, 2, 3, 4],
[4, 5, 6, 7]])
In [46]: data1 * 4
Out[46]:
array([[ 4, 8, 12, 16],
[16, 20, 24, 28]])
In [47]: data1 ** 2
Out[47]:
array([[ 1, 4, 9, 16],
[16, 25, 36, 49]])
In [48]: data1 - 2
Out[48]:
array([[-1, 0, 1, 2],
[ 2, 3, 4, 5]])
In [49]: 1 / data1
Out[49]:
array([[1. , 0.5 , 0.33333333, 0.25 ],
[0.25 , 0.2 , 0.16666667, 0.14285714]])
- 数组与数组间的运算:
In [51]: data1
Out[51]:
array([[0, 1, 2],
[3, 4, 5],
[6, 7, 8]])
In [52]: data2 = ones((3,3)) * 2
In [53]: data2
Out[53]:
array([[2., 2., 2.],
[2., 2., 2.],
[2., 2., 2.]])
In [54]: data1 + data2
Out[54]:
array([[ 2., 3., 4.],
[ 5., 6., 7.],
[ 8., 9., 10.]])
In [55]: data1 * data2
Out[55]:
array([[ 0., 2., 4.],
[ 6., 8., 10.],
[12., 14., 16.]])
In [56]: data1 ** data2
Out[56]:
array([[ 0., 1., 4.],
[ 9., 16., 25.],
[36., 49., 64.]])
In [57]: data1 - data2
Out[57]:
array([[-2., -1., 0.],
[ 1., 2., 3.],
[ 4., 5., 6.]])
3.快速的元素级数组函数
#random.randn返回一个用随机值填充的数组
#Numpy中有许多用于数组元素的运算函数
In [143]: data = random.randn(10)
In [144]: data
Out[144]:
array([-0.25025256, -0.51688418, 0.29202827, -0.40138525, 1.30740859,
-0.63296315, 0.54725757, 0.04679136, -1.19511119, -1.18405447])
#求绝对值的
In [145]: fabs(data)
Out[145]:
array([0.25025256, 0.51688418, 0.29202827, 0.40138525, 1.30740859,
0.63296315, 0.54725757, 0.04679136, 1.19511119, 1.18405447])
#求e^x的
In [146]: exp(data)
Out[146]:
array([0.77860411, 0.59637586, 1.33914088, 0.66939213, 3.69658193,
0.53101598, 1.72850621, 1.04790335, 0.3026703 , 0.30603541])
#二元运算的
In [148]: x = random.randn(10)
In [149]: y = random.randn(10)
In [154]: x
Out[154]:
array([-0.06476071, -1.1714078 , 0.38681559, -1.71718398, -0.69387862,
-0.34142624, -0.57579345, -0.93740606, 1.03938051, 0.14597888])
In [155]: y
Out[155]:
array([-0.11114039, 1.28650201, -0.93268421, 1.1055424 , 0.53798898,
0.36172126, -0.04537335, 1.98738716, 0.24726811, -0.465419 ])
#相加的
In [151]: add(x, y)
Out[151]:
array([-0.1759011 , 0.11509421, -0.54586862, -0.61164158, -0.15588964,
0.02029502, -0.6211668 , 1.04998111, 1.28664861, -0.31944012])
#比较大小的
In [152]: maximum(x, y)
Out[152]:
array([-0.06476071, 1.28650201, 0.38681559, 1.1055424 , 0.53798898,
0.36172126, -0.04537335, 1.98738716, 1.03938051, 0.14597888])
下面是一元运算函数
函数 | 作用 |
---|---|
abs, fabs | 计算整数,浮点数或者复数的绝对值,对于非复数,fabs速度更快 |
sqrt | 计算平方根 |
square | 计算平方 |
exp | 计算指数e^x |
log, log10, log2, log1p | 计算自然对数,底数为10的对数,底数为2的对数,底数为1+ x的对数 |
sign | 计算正负号,1为整数,0为0, -1为负数 |
ceil | 向上取整 |
floor | 向下取整 |
rint | 四舍五入的取整 |
modf | 将数组的小数与整数部分分开并返回2个数组 |
isnan | 判断是否为nan,返回布尔数组 |
isfinite, isinf | 判断是否为有穷, 返回布尔数组 |
cos, cosh,sin, sinh, tan. tanh | 三角函数 |
logical_not | 逻辑否运算,返回布尔数组 |
还有二元的运算
函数 | 作用 |
---|---|
add | 加运算 |
subtract | 减运算 |
multiply | 乘运算 |
divide, floor_divide | 除运算 |
power | 指数运算,A^B |
maximum, fmax | 求最大值,fmax忽略nan |
minimum, fmin | 求最小值,fmin忽略nan |
mod | 元素级的取模 |
copysign | 将第二个数组的符号复制给第一个数组中的值 |
greater, greater_equal,less,less_equal,equal, not_equal | 大于,大于等于等比较 |
logical_and, logical_or, logical_xor | 执行元素级的and, or, not |
5.数组切片
- 这里切片方式很多,1维的切片和python数组1维切片是一样的。有一点比较关键的时你对数组切片进行操作时,实际上也操作了原数组。
In [58]: data = array(arange(9))
In [59]: data
Out[59]: array([0, 1, 2, 3, 4, 5, 6, 7, 8])
In [60]: data[3:7]
Out[60]: array([3, 4, 5, 6])
In [61]: data[:3] *= 3
In [62]: data
Out[62]: array([0, 3, 6, 3, 4, 5, 6, 7, 8])
- 难的是多维的切片和索引
#这是索引基本方式
In [66]: data = array(arange(16).reshape((2, 2, 4)))
In [67]: data
Out[67]:
array([[[ 0, 1, 2, 3],
[ 4, 5, 6, 7]],
[[ 8, 9, 10, 11],
[12, 13, 14, 15]]])
In [68]: data[0][1][3]
Out[68]: 7
#这种方式与上面是等价的
In [69]: data[0, 1, 3]
Out[69]: 7
In [70]: data[0,1]
Out[70]: array([4, 5, 6, 7])
#用布尔数组来切片
In [86]: arr = array(['a', 'b', 'a' ,'c', 'd', 'c', 'a'])
#布尔数组的长度必须与被索引的轴一样长
In [87]: data = array(arange(28).reshape((7, 4)))
In [88]: data
Out[88]:
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]])
In [89]: arr == 'a'
Out[89]: array([ True, False, True, False, False, False, True])
In [90]: data[arr == 'a']
Out[90]:
array([[ 0, 1, 2, 3],
[ 8, 9, 10, 11],
[24, 25, 26, 27]])
#基本切片方式
In [101]: data
Out[101]:
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]])
In [102]: data[:2, 2:4]
Out[102]:
array([[2, 3],
[6, 7]])
In [103]: data[:2]
Out[103]:
array([[0, 1, 2, 3],
[4, 5, 6, 7]])
#布尔索引加切片
In [105]: data[arr != 'a', 2:]
Out[105]:
array([[ 6, 7],
[14, 15],
[18, 19],
[22, 23]])
In [110]: data[(arr != 'b') & (arr != 'a')] = 0
#这种判断并赋值的方法经常用
In [111]: data
Out[111]:
array([[ 0, 1, 2, 3],
[ 4, 5, 6, 7],
[ 8, 9, 10, 11],
[ 0, 0, 0, 0],
[ 0, 0, 0, 0],
[ 0, 0, 0, 0],
[24, 25, 26, 27]])
#下面用一个整型数组的索引方式,来选取特定的行子集
In [119]: arr = array([array([1, 1, 1, 1 ]) * i for i in range(8)])
In [120]: arr
Out[120]:
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 [121]: arr[[4, 3, 0, 6]]
Out[121]:
array([[4, 4, 4, 4],
[3, 3, 3, 3],
[0, 0, 0, 0],
[6, 6, 6, 6]])
In [122]: arr[[-3, -5, -1]]
Out[122]:
array([[5, 5, 5, 5],
[3, 3, 3, 3],
[7, 7, 7, 7]])
#用两个数组的索引的
In [123]: data = array(arange(32).reshape((8, 4)))
In [124]: data
Out[124]:
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]])
#请一对一对的看,即(1,0),(5,3),(7,1),(2,2)
In [125]: data[[1, 5, 7, 2], [0, 3, 1, 2]]
Out[125]: array([ 4, 23, 29, 10])
#还行吧,并不很难,下面的就更奇怪了
#切片加数组索引
In [127]: data[[1, 5, 7,2]][:, [0, 3, 1, 2]]
Out[127]:
array([[ 4, 7, 5, 6],
[20, 23, 21, 22],
[28, 31, 29, 30],
[ 8, 11, 9, 10]])
#分解一下
In [128]: data[[1, 5, 7,2]]
Out[128]:
array([[ 4, 5, 6, 7],
[20, 21, 22, 23],
[28, 29, 30, 31],
[ 8, 9, 10, 11]])
In [129]: data[[1, 5, 7,2]][:]
Out[129]:
array([[ 4, 5, 6, 7],
[20, 21, 22, 23],
[28, 29, 30, 31],
[ 8, 9, 10, 11]])
In [130]: data[[1, 5, 7,2]][:,[0, 1, 2, 3]]
Out[130]:
array([[ 4, 5, 6, 7],
[20, 21, 22, 23],
[28, 29, 30, 31],
[ 8, 9, 10, 11]])
#到这里我想你应该看出来这是什么意思了
6.用where() 来简化x if condition else y
#假如我要对x 与y 数组里面的每个元素执行 x if condition else y操作,那么一般来说我可以么写
In [156]: x = array([1.1, 1.2, 1.3, 1.4, 1.5])
In [157]: y = array([2.1, 2.2, 2.3, 2.4, 2.5])
In [158]: cond = array([True, False, True, True, False])
In [160]: result = [(xa if ca else ya) for (xa, ya ,ca) in zip(x, y, cond)]
In [161]: result
Out[161]: [1.1, 2.2, 1.3, 1.4, 2.5]
#这样写又长又难看懂,并且在数据多的情况下速度比较慢(因为这种操作底层是python)
#Numpy这时为我们提供了where()
In [162]: result = where(cond, x, y)
In [163]: result
Out[163]: array([1.1, 2.2, 1.3, 1.4, 2.5])
#或者当想将result中大于2的全部置换为0,可以像下面这样
In [164]: res = where(result > 2, 0,result)
In [165]: res
Out[165]: array([1.1, 0. , 1.3, 1.4, 0. ])
7. Numpy中的数学与统计方法
- 统计函数
|方法| 作用 |
|–|--|
| sum | 对某一个轴累加 |
|mean|对某一个轴求平均数
|std, var|求标准差与方法,自由度可调
|min, max|求最大与最小值
|argmin, argmax|求最大值与最小值的索引
|cumsum|所有元素的累计和
|cumprod|所有元素的累计积
In [171]: data = arange(16).reshape((4,4))
In [172]: data
Out[172]:
array([[ 0, 1, 2, 3],
[ 4, 5, 6, 7],
[ 8, 9, 10, 11],
[12, 13, 14, 15]])
In [173]: data.mean(axis=1)
Out[173]: array([ 1.5, 5.5, 9.5, 13.5])
In [174]: data.mean(axis=0)
Out[174]: array([6., 7., 8., 9.])
In [177]: data.sum(axis=1)
Out[177]: array([ 6, 22, 38, 54])
In [178]: data.sum(axis=0)
Out[178]: array([24, 28, 32, 36])
- 用于布尔数组的方法
In [179]: data = array([True, True, False, True, False, False])
#sum()可用与计算数组中True数量(True与False会被转成1, 0)
In [180]: data.sum()
Out[180]: 3
#any()用于判断数组里面有无True
In [181]: data.any()
Out[181]: True
#all()用于判断数组里面是否全都为True
In [182]: data.all()
Out[182]: False
- 集合运算方法
方法 | 作用 |
---|---|
unique | 计算唯一结果,并返回有序结果 |
intersect1d | 求交集 |
union1d | 求并集 |
in1d | 得到一个x in y的布尔数组 |
setdiff1d | 集合差运算 |
setxor1d | 对称差运算 |
In [190]: arr = array(list('successful'))
#unique这方法经常用
In [191]: unique(arr)
Out[191]: array(['c', 'e', 'f', 'l', 's', 'u'], dtype='<U1')
In [192]: arr2 = array(list('abcdefg'))
In [193]: in1d(arr, arr2)
Out[193]:
array([False, False, True, True, True, False, False, True, False,
False])
8.线代方法
Numpy为我们提供了许多线性代数中的方法,这里有许多方法得引入numpy.linalg(如下面的inv, qr)
In [200]: x = array(arange(6).reshape(2,3), dtype = float)
In [201]: y = array([[6., 23.], [-1., 7.], [8.,9.]])
#数组转置
In [202]: x.T
Out[202]:
array([[0., 3.],
[1., 4.],
[2., 5.]])
#数组乘法
In [203]: x.dot(y)
Out[203]:
array([[ 15., 25.],
[ 54., 142.]])
#求对角线的和
In [204]: x.trace()
Out[204]: 4.0
方法 | 作用 |
---|---|
dot | 矩阵点乘 |
diag | 返回对角线的一维数组 |
trance | 计算对角线累加和 |
det | 计算行列式 |
eig | 计算特征值与特征向量 |
inv | 计算逆矩阵 |
qr | 计算qr分解 |
svd | 计算奇异值分解 |
solve | 解Ax=b |
lsts | 计算Ax=b的最小二乘解 |
9.随机值的生成
这里得引入numpy.random,上面的randn便是这里面的
方法 | 作用 |
---|---|
seed | |
permutation | 返回一个序列的随机排列 |
shuffle | 对一个序列随机排列 |
rand | 产生均匀分布的样本 |
randn | 产生正态分布的样本 |
binomial | 产生二项分布的样本 |
normal | 产生正态(高斯)分布的样本 |
beta | 产生Beta分布的样本 |
chisquare | 产生卡方分布的样本 |
gamma | 产生gamma分布的样本 |
uniform | 产生0到1中均匀分布的样本 |