numpy学习笔记

简介

Numpy(发音"南派"而不是"努屁")是一款用来进行科学计算的python库,可以方便快速的计算平均值、最大值、最小值、方差、标准差、向量运行等。相关库还有 Pandas,Scypi等。

数组

Numpy中用数组来表示数据,和Python中的列表相比,除了提供了一些更快、更方便的函数外,最大的区别就在于前者同一数组内的元素类型必须一致,而后者则无此要求。


In [1]: import numpy as np

In [2]: np.array([1,2,3,4,5]) # 创建一个numpy数组
Out[2]: array([1, 2, 3, 4, 5])

In [3]: np.array([1,2,3,4,5]).dtype # 查看元素类型
Out[3]: dtype('int64')

In [4]: np.max([1,2,3,4,5]) # 最大值
Out[4]: 5

In [5]: np.min([1,2,3,4,5]) # 最小值
Out[5]: 1

In [6]: np.std([1,2,3,4,5]) # 标准差
Out[6]: 1.4142135623730951

In [7]: np.mean([1,2,3,4,5]) # 平均值
Out[7]: 3.0

In [8]: np.array([1,2,1.2,4,'a']) # 声明时候就不按套路出牌,可以发现最后都变成了字符串
Out[8]:
array(['1', '2', '1.2', '4', 'a'],
      dtype='|S32')

In [9]: a = np.array([[1,2],[3,4]]) # 定义二维数组

In [10]: a[:,1] # 取第2列
Out[10]: array([2, 4])

In [11]: a[1,:] # 取第2行
Out[11]: array([3, 4])

In [12]: a[1,1] # 取某个值
Out[12]: 4

In [13]: a[1,1:] # 使用切片
Out[13]: array([4])

运算

Numpy中的运算都是向量运算,支持加、减、乘、除、指数运算以及与、或、非这类逻辑运算,

In [35]: a=np.array([5,3,1])

In [36]: b=np.array([2,4,6])

In [37]: a+b
Out[37]: array([7, 7, 7])

In [38]: a-b
Out[38]: array([ 3, -1, -5])

In [39]: a*b
Out[39]: array([10, 12,  6])

In [40]: a/b
Out[40]: array([2, 0, 0])

In [41]: a**b
Out[41]: array([25, 81,  1])

In [42]: a&b
Out[42]: array([0, 0, 0])

In [43]: a|b
Out[43]: array([7, 7, 7])

In [44]: ~a
Out[44]: array([-6, -4, -2])

这里注意py2版本的除法默认是取结果整数部分的,另外需要注意Numpy中++=有些区别,比如:

In [67]: a = np.array([2,3,4])

In [68]: b = a

In [69]: a += 1

In [70]: b
Out[70]: array([3, 4, 5])

In [71]: a
Out[71]: array([3, 4, 5])

In [72]: a = a + 1

In [73]: a
Out[73]: array([4, 5, 6])

In [74]: b
Out[74]: array([3, 4, 5])

可以看出,对于+=操作是修改了数组本身的值,而+操作则是创建了一个新的数组赋值给了变量a。 +=操作的行为叫做原位运算(In-Place),+操作则是非原位运算(Not In-Place)。对于切片操作,Numpy的行为和Python不同:

In [75]: a
Out[75]: array([4, 5, 6])

In [76]: e = [1,2,3]

In [77]: f = e[:2]

In [78]: f
Out[78]: [1, 2]

In [79]: f[0]= 9

In [80]: f
Out[80]: [9, 2]

In [81]: e
Out[81]: [1, 2, 3]

In [82]: a
Out[82]: array([4, 5, 6])

In [83]: g = a[:2]

In [84]: g
Out[84]: array([4, 5])

In [85]: g[0] = 8

In [86]: g
Out[86]: array([8, 5])

In [87]: a
Out[87]: array([8, 5, 6])

Python中切片操作创建了一个新的列表出来,改变新的列表值不会影响旧列表。而Numpy中的切片还是指向原来的值,会互相影响。

索引数组

假设有2个数组的 长度一样,一个数组类型为整型,另一个数组的类型为布尔型,则

In [45]: a
Out[45]: array([5, 3, 1])

In [46]: c = np.array([True,False,True])

In [47]: a[c]
Out[47]: array([5, 1])

In [48]: a[a!=3]
Out[48]: array([5, 1])

In [49]: a != 3
Out[49]: array([ True, False,  True], dtype=bool)

数组c为索引数组(index array),除此之外可以直接在数组索引中使用逻辑判断达到同样的效果。也就是说,对一个数组进行逻辑判断后 返回的结果是一个索引数组。

当使用Numpy处理二维数组时候,就会涉及到轴(axis)这个概念,轴用来控制行或者列的平均值、最大最小值、标准差等的计算:

In [3]: a = np.array([[1,2],[3,4]])

In [4]: a
Out[4]:
array([[1, 2],
       [3, 4]])

In [5]: a.mean()
Out[5]: 2.5

In [6]: a.mean(axis=0)
Out[6]: array([ 2.,  3.])

In [7]: a.mean(axis=1)
Out[7]: array([ 1.5,  3.5])

这里声明了一个二维数组,当mean函数不添加任何参数时,默认计算了整个数据的平均值。当axis=0时则计算出每一列的平均值,axis=1时则计算每一行的平均值。 其他计算函数同理。

标准化

用于将数据进行标准化(standardized)处理,即(单值-平均数)/标准差,为啥要进行标准化处理呢?我觉得是为了减少两组变量之间由于取值区间差异过大而产生的问题。 比如:

In [60]: a
Out[60]: array([ 1,  3,  5,  7,  9, 11])

In [61]: b
Out[61]: array([5000, 4000, 3000, 2000, 1000,   50])

In [63]: a_s = (a-a.mean())/a.std()
In [64]: b_s = (b-b.mean())/b.std()

In [69]: a_s
Out[69]:
array([-1.46385011, -0.87831007, -0.29277002,  0.29277002,  0.87831007,
        1.46385011])

In [70]: b_s
Out[70]:
array([ 1.4694161 ,  0.87968389,  0.28995167, -0.29978054, -0.88951276,
       -1.44975836])

可以看出,在进行标准化后a和b的取值区间差异变得很小了。

相关系数

使用皮尔逊积矩相关系数来计算2个变量的相关度,这里需要注意的是2个变量之间需要有线性关系,变量是连续变量,变量符合正态分布。

计算皮尔逊相关系数可以分为2步:

  1. 将数据标准化
  2. 标准化的数据进行乘法运算,并取结果的平均值
def correlation(x, y):
    tempx = (x-x.mean()) / x.std()
    tempy = (y-y.mean()) / y.std()
    return (tempx * tempy).mean()

另外Numpy中已经提供了函数corrcoef可以直接使用:

In [68]: correlation(a_s,b_s)
Out[68]: -0.99996549701548165

In [65]: np.corrcoef(a_s,b_s)
Out[65]:
array([[ 1.       , -0.9999655],
       [-0.9999655,  1.       ]])

可以看出和自己编写的函数结果是一样的。