ndarry:一种多维数组对象 ##
- numpy的重要特点是N维对象,是一个快速而灵活的大数据集容器
数组和标量之间的运算
数组不用编写循环即可对数据执行批量运算,这叫做矢量化
1、新建数组
In [9]: arr
Out[9]:
array([[1., 2., 3.],
[4., 5., 6.]])
- 2、数组之间的运算
乘法
In [10]: arr*arr
Out[10]:
array([[ 1., 4., 9.],
[16., 25., 36.]])
减法
In [11]: arr -arr
Out[11]:
array([[0., 0., 0.],
[0., 0., 0.]])
除法
In [12]: 1/arr
Out[12]:
array([[1. , 0.5 , 0.33333333],
[0.25 , 0.2 , 0.16666667]])
索引切片技巧
数组和列表最重要的区别在于,数组切片是原始数组的试图,这意味着数据不会被复制,试图上的任何修改都会直接反应到原数组上
In [15]: arr
Out[15]: array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])
In [17]: arr[5:8] = 12
In [18]: arr
Out[18]: array([ 0, 1, 2, 3, 4, 12, 12, 12, 8, 9])
In [19]: arr_slice = arr[5:8]
In [20]: arr_slice[1] = 1234
In [21]: arr
Out[21]: array([ 0, 1, 2, 3, 4, 12, 1234, 12, 8, 9])
- 高维数组切片
In [29]: arr2d = np.array([[1,2,3],[4,5,6],[7,8,9]])
In [30]: arr2d
Out[30]:
array([[1, 2, 3],
[4, 5, 6],
[7, 8, 9]])
In [31]: arr2d[:2,1:]
Out[31]:
array([[2, 3],
[5, 6]])
数组切片替换
In [33]: arr2d[:2,1:] = 0
In [34]: arr2d
Out[34]:
array([[1, 0, 0],
[4, 0, 0],
[7, 8, 9]])
布尔型索引
布尔型索引和数组索引混合使用
In [36]: names
Out[36]: array(['Bob', 'Joe', 'Will', 'Bob', 'Will', 'Joe', 'Joe'], dtype='<U4')
In [37]: data = np.random.randn(7,4)
In [38]: names
Out[38]: array(['Bob', 'Joe', 'Will', 'Bob', 'Will', 'Joe', 'Joe'], dtype='<U4')
In [39]: data
Out[39]:
array([[ 0.7376864 , -0.14042845, 0.656145 , 1.56401402],
[ 0.37511586, 1.03808552, -1.11753394, 1.15265036],
[-1.73233955, 0.16149212, 0.39760093, -0.68995195],
[-0.45980994, -0.9902711 , 0.60236354, -0.14960381],
[ 0.04820651, -0.76681058, 0.63870274, 1.8714127 ],
[ 0.98703728, 0.64788133, -0.05041069, -1.34046398],
[-0.62428209, -0.05168078, -0.62277132, -0.92203116]])
In [40]: names == 'Bob'
Out[40]: array([ True, False, False, True, False, False, False])
In [41]: data [names == 'Bob']
Out[41]:
array([[ 0.7376864 , -0.14042845, 0.656145 , 1.56401402],
[-0.45980994, -0.9902711 , 0.60236354, -0.14960381]])
数组的索引嵌套布尔索引的值
In [51]: mask
Out[51]: array([ True, False, False, True, False, False, False])
In [52]: data[mask]
Out[52]:
array([[ 0.7376864 , -0.14042845, 0.656145 , 1.56401402],
[-0.45980994, -0.9902711 , 0.60236354, -0.14960381]])
通过布尔类型数组设置值
In [55]: data[data < 0] = 0
In [56]: data
Out[56]:
array([[0.7376864 , 0. , 0.656145 , 1.56401402],
[0.37511586, 1.03808552, 0. , 1.15265036],
[0. , 0.16149212, 0.39760093, 0. ],
[0. , 0. , 0.60236354, 0. ],
[0.04820651, 0. , 0.63870274, 1.8714127 ],
[0.98703728, 0.64788133, 0. , 0. ],
[0. , 0. , 0. , 0. ]])
In [57]: data [names != 'Joe'] = 7
In [58]: data
Out[58]:
array([[7. , 7. , 7. , 7. ],
[0.37511586, 1.03808552, 0. , 1.15265036],
[7. , 7. , 7. , 7. ],
[7. , 7. , 7. , 7. ],
[7. , 7. , 7. , 7. ],
[0.98703728, 0.64788133, 0. , 0. ],
[0. , 0. , 0. , 0. ]])
花式索引(Fancy indexing)
- 利用整数数组进行索引
In [70]: arr[[1,5,7,2],[0,3,1,2]]
Out[70]: array([ 4, 23, 29, 10])
In [71]: arr
Out[71]:
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 [71]: arr
Out[71]:
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 [72]:
In [72]: arr[[1,5,7,2]][:,[0,3,1,2]]
Out[72]:
array([[ 4, 7, 5, 6],
[20, 23, 21, 22],
[28, 31, 29, 30],
[ 8, 11, 9, 10]])
np.ix_函数,将两个一纬整数数组转换为一个用于选区方形区域的索引器
In [75]: arr[np.ix_([1,5,7,2],[0,3,1,2])]
Out[75]:
array([[ 4, 7, 5, 6],
[20, 23, 21, 22],
[28, 31, 29, 30],
[ 8, 11, 9, 10]])
数组转置和轴对换
转置(transpose)是重塑的一种特殊形式,它返回的是源数据的视图(不会进行任何的复制操作)
数组的特殊T属性:
In [77]: arr
Out[77]:
array([[ 0, 1, 2, 3, 4],
[ 5, 6, 7, 8, 9],
[10, 11, 12, 13, 14]])
In [78]: arr.T
Out[78]:
array([[ 0, 5, 10],
[ 1, 6, 11],
[ 2, 7, 12],
[ 3, 8, 13],
[ 4, 9, 14]])
- T属性的利用,利用np.dot计算矩阵内积X T X:
In [79]: arr = np.random.randn(6,3)
In [80]: np.dot(arr.T,arr)
Out[80]:
array([[ 5.74661921, -3.89670236, -0.37968544],
[-3.89670236, 4.71932223, 1.08395255],
[-0.37968544, 1.08395255, 4.28373954]])
通用函数:快速的元素级数组函数
- 通用函数是一种对ndarray中的数据执行元素级运算的函数
- 通用函数涉及数学计算较多,我等数学渣渣使用场景不多
In [3]: arr = np.arange(10)
In [4]: arr
Out[4]: array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])
In [5]: np.sqrt(arr)
Out[5]:
array([0. , 1. , 1.41421356, 1.73205081, 2. ,
2.23606798, 2.44948974, 2.64575131, 2.82842712, 3. ])
In [6]: np.exp(arr)
Out[6]:
array([1.00000000e+00, 2.71828183e+00, 7.38905610e+00, 2.00855369e+01,
5.45981500e+01, 1.48413159e+02, 4.03428793e+02, 1.09663316e+03,
2.98095799e+03, 8.10308393e+03])
In [7]: np.modf(arr)
Out[7]:
(array([0., 0., 0., 0., 0., 0., 0., 0., 0., 0.]),
array([0., 1., 2., 3., 4., 5., 6., 7., 8., 9.]))
利用数组进行数据处理
numpy数组可以将许多数据处理人物表诉为简介的数组表达式,数组表达式替代循环的做法被称为矢量化
numpy.where函数
In [18]: xarr = np.array([1.1,1.2,1.3,1.4,1.5])
In [19]: yarr = np.array([2.1,2.2,2.3,2.4,2.5])
In [20]: cond = np.array([True,False,True,True,False])
In [21]: result = [(x if c else y) for x,y,c in zip(xarr,yarr,cond)]
In [22]: result
Out[22]: [1.1, 2.2, 1.3, 1.4, 2.5]
In [23]: result = np.where(cond,xarr,yarr)
In [24]: result
Out[24]: array([1.1, 2.2, 1.3, 1.4, 2.5])
- 利用np.where将随机数组所有的正值替换为2,将所有负值替换成-2
In [27]: np.where(arr >0 , 2, -2)
Out[27]:
array([[-2, 2, 2, -2],
[ 2, -2, -2, 2],
[ 2, 2, -2, -2],
[ 2, -2, -2, -2]])
数学和统计方法
- sum、mean以及标准差std等聚合计算既可以当作数组的实例方法调用,也可以当作顶级numpy函数使用
- mean取数组的平均值
In [29]: arr.mean()
Out[29]: -0.05527682160532713
取数组所有数的和
In [31]: arr.sum()
Out[31]: -1.1055364321065426
- cumsum:产生一个由中间结果组成的数组
In [47]: arr
Out[47]:
array([[0, 1, 2],
[3, 4, 5],
[6, 7, 8]])
cumsum:所有元素的累计和
cumprod:所有元素的累计积
In [48]: arr.cumsum()
Out[48]: array([ 0, 1, 3, 6, 10, 15, 21, 28, 36], dtype=int32)
cumsum(0): 降维累加,这里是[3,3]的数组,数组元素和他上一个数组的同位相加
In [49]: arr.cumsum(0)
Out[49]:
array([[ 0, 1, 2],
[ 3, 5, 7],
[ 9, 12, 15]], dtype=int32)
In [51]: arr
Out[51]:
array([[0, 1, 2],
[3, 4, 5],
[6, 7, 8]])
cumprod(1):每行和前面连续相乘
In [53]: arr.cumprod(1)
Out[53]:
array([[ 0, 0, 0],
[ 3, 12, 60],
[ 6, 42, 336]], dtype=int32)
cumprod(0): 每行和上一行同一元素相乘
In [54]: arr.cumprod(0)
Out[54]:
array([[ 0, 1, 2],
[ 0, 4, 10],
[ 0, 28, 80]], dtype=int32)
用于布尔型数组的方法
布尔值会被强制转换为1(True)和0(False),sum经常被用来对布尔型数组的True值计数
统计数组中大于0的个数
In [57]: (arr > 0).sum()
Out[57]: 52
In [58]: bools = np.array([False,False,True,False])
any用于测试数组中是否存在一个或多个True
In [59]: bools.any()
Out[59]: True
all用于检查数组中所有值是否都是True
In [60]: bools.all()
Out[60]: False
排序
- sort方法进行排序
In [66]: arr
Out[66]:
array([[ 0.06833228, -2.77714594, -0.57015833],
[-1.44599612, -1.73215144, -0.36345215],
[ 0.40153326, -0.34907017, -0.83628199],
[-2.13061776, 0.42451388, 0.94227795],
[ 0.5132763 , 0.98194904, 0.09912724]])
In [67]: arr.sort(1)
In [68]: arr
Out[68]:
array([[-2.77714594, -0.57015833, 0.06833228],
[-1.73215144, -1.44599612, -0.36345215],
[-0.83628199, -0.34907017, 0.40153326],
[-2.13061776, 0.42451388, 0.94227795],
[ 0.09912724, 0.5132763 , 0.98194904]])
np.sort返回的是数组的已排序副本
唯一化以及其他的集合逻辑
- numpy提供一纬ndarray的基本集合运算,最常用的是np.unique
In [73]: names = np.array(['Bob','Joe','Will','Bob','Will','Joe','Joe','Joe','Joe'])
In [74]: names
Out[74]:
array(['Bob', 'Joe', 'Will', 'Bob', 'Will', 'Joe', 'Joe', 'Joe', 'Joe'],
dtype='<U4')
In [76]: np.unique(names)
Out[76]: array(['Bob', 'Joe', 'Will'], dtype='<U4')
- np.in1d用于测试一个数组中的值再另一个数组中的成员资格,返回一个布尔型数组
In [78]: values = np.array([6,0,0,3,2,5,6])
In [79]: np.in1d(values,[2,3,6])
Out[79]: array([ True, False, False, True, True, False, True])
数组以二进制格式保存到磁盘
- np.save和np.load是读写磁盘数组数据的两个主要函数,数组是以未亚索的原始二进制格式保存再扩展名.npy的文件中
np.save使用
In [79]: np.in1d(values,[2,3,6])
Out[79]: array([ True, False, False, True, True, False, True])
In [80]: arr = np.array(10)
In [81]: np.save('some_array',arr)
np.save 可以数组保存到一个压缩文件中
np.save('array_archive.npz',a=arr, b=arr)
np.load读取磁盘上的数组
In [86]: np.load('some_array.npy')
Out[86]: array(10)
np.savez可以将多个数组保存到压缩文件中,数组以关键参数的形式传入
In [88]: arr
Out[88]: array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])
In [89]: np.savez('array_archive.npz',a=arr,b=arr)
load加载.npz文件时,得到一个类似字典的对象
In [90]: arch = np.load('array_archive.npz')
In [91]: arch
Out[91]: <numpy.lib.npyio.NpzFile at 0x258aff3c0b8>
In [92]: arch['b']
Out[92]: array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])
线性代数
线性代数(矩阵乘法、矩阵分解、行列式以及其他方阵数学等)是任何数组库的重要组成部分
numpy提供了一个用于矩阵乘法的dot函数
- dot矩阵所得到的数组中的每个元素为,第一个矩阵中与该元素行号相同的元素与第二个矩阵与该元素列号相同的元素,两两相乘后再求和。
In [96]: x
Out[96]:
array([[1., 2., 3.],
[4., 5., 6.]])
In [97]: y
Out[97]:
array([[ 6., 23.],
[-1., 7.],
[ 8., 9.]])
In [98]: x.dot(y)
Out[98]:
array([[ 28., 64.],
[ 67., 181.]])
- numpy.linalg有一组标准的矩阵分解运算以及诸如求逆和行列式之类的东西
随机数生成
- numpy.random模块对Python内置的random进行补充,可以用normal得到一个标准正态分布
In [11]: samples = np.random.normal(size=(4,4))
In [12]: samples
Out[12]:
array([[ 0.63344344, 0.55240025, 1.38685779, -1.06955571],
[-2.58502025, -0.7375224 , -0.13867335, 0.90274877],
[ 2.45626551, 0.36809146, -0.35775548, -0.87478656],
[-0.59736952, 0.30550005, -0.62660048, -0.61322287]])
一次模拟多个随机漫步
In [22]: nwalks = 5000
In [23]: nsteps = 1000
In [25]: draws = np.random.randint(0,2,size=(nwalks,nsteps)) #生成一个nwalks行,nsteps列的二维数组
In [26]: steps = np.where(draws >0,1,-1)
In [27]: walks = steps.cumsum(1)
In [28]: walks
Out[28]:
array([[ 1, 2, 1, ..., -4, -5, -6],
[ 1, 0, 1, ..., -10, -9, -8],
[ 1, 2, 3, ..., -30, -29, -28],
...,
[ 1, 2, 3, ..., 14, 15, 14],
[ -1, -2, -3, ..., -8, -7, -8],
[ -1, 0, 1, ..., -44, -45, -46]], dtype=int32)
In [31]: walks.min()
Out[31]: -133
In [32]: walks.max()
Out[32]: 122