Numpy

1. Numpy介绍

Numpy是python开源的科学计算工具包,具有高级的数值编程工具。它是许多高级工具的开发基础,如后续要介绍的pandas包就是在Numpy的基础上开发来的。学习Numpy我们主要关注3个核心点:
(1)强大的N维数组对象:ndarray
(2)对数组结构数据进行计算(无需遍历循环)
(3)随机数、线性代数、傅里叶变换等功能

2. 创建数组

在介绍如何使用Numpy创建数组之前,我们需要简要说明一下,通常我们使用Numpy包时会使用如下语句进行导入。

import numpy as np

注意:数组与列表的区别,数组的格式:中括号,但是元素之间没有逗号,而列表是有逗号的
使用Numpy创建数组主要有如下几种方式:
(1)使用array()函数,其中括号内可以是列表、元组、数组、生成器等

ar1 = np.array(['Bob', True, 88, {'age':23}])
ar2 = np.array(('a', 5, True, None))
ar3 = np.array(range(10))
print(ar1)  >>>['Bob' True 88 {'age': 23}]
print(ar2) >>>['a' 5 True None]
print(ar3) >>> [0 1 2 3 4 5 6 7 8 9]

(2)使用arange()函数,类似于range(),在给定间隔内返回均匀间隔的值

print(np.arange(10))  ------------------------------[0 1 2 3 4 5 6 7 8 9]
print(np.arange(0,10,2)) --------------------------[0 2 4 6 8]
print(np.arange(5.0, 13, 3)) ----------------------[ 5.  8. 11.]
print(np.arange(10000)) --------------------------[   0    1    2 ... 9997 9998 9999]

注意:如果数组太大而无法打印,Numpy会自动跳过数组的中心部分,只打印边角
(3)使用linspace()函数,返回在间隔[start, stop]上计算的num个均匀间隔样本
numpy.linspace(start, stop, num=50, endpoint=True, retstep=False, dtype=None)

  • start:起始值
  • stop:结束值
  • num:生成样本数,默认为50
  • endpoint:如果为真,则[start, stop]是左闭右闭,否则为左闭右开,默认为左闭右闭
  • retstep:如果为真,返回一个包含2个元素的元组,第一个元素为array,第二个为步长实际值,其中步长为样本元素之间的距离
ar1 = np.linspace(10, 20, num=10)
ar2 = np.linspace(10, 20, num=10, endpoint=False)
ar3 = np.linspace(10, 20, num=10, retstep=True)
ar4 = np.linspace(10, 20, num=10, endpoint=False, retstep=True)
print(ar1) >>>[10. 11.11111111 12.22222222 13.33333333 14.44444444 15.55555556  16.66666667 17.77777778 18.88888889 20.     ]  
print(ar2) >>>[10. 11. 12. 13. 14. 15. 16. 17. 18. 19.]
print(ar3) >>>(array([10. , 11.11111111, 12.22222222, 13.33333333, 14.44444444, 15.55555556, 16.66666667, 17.77777778, 18.88888889, 20.  ]), 1.1111111111111112)
print(ar4) >>>(array([10., 11., 12., 13., 14., 15., 16., 17., 18., 19.]), 1.0)

3. Numpy常用的属性

array.ndim:数组的维度/秩,描述的是轴axes的数量
array.shape:数组的行列数,对n行m列的数组,shape为(n,m)
array.size:数组的元素的总个数n*m
array.dtype:数组中元素的类型,类似于type,但是type是函数,dtype是属性/方法
array.itemsize:数组中每个元素的 字节 大小,int32为4字节,float64为8字节
array.data:包含实际数组元素的缓冲区,由于一般通过数组的索引获取元素,所以通常不需要使用这个属性。

import numpy as np
ar = np.array([[1,2,3,4,5], [6, 7, 8, 9, 10]]) #二维数组
print(ar, type(ar))  >>>[[ 1  2  3  4  5]  [ 6  7  8  9 10]] 
print(ar.ndim) >>> 2
print(ar.shape) >>>(2,5)
print(ar.size) >>> 10
print(type(ar), ar.dtype)  >>>  int32
print(ar.itemsize) >>> 4
print(ar.data) >>> 

注意:对于二维数组而言,如果两个列表元素个数不一致,那么此时生成的是一个一维数组

ar1 = np.array([[1,2,3,4], ['a', 'b', 'c', 'd']])
print(ar1, ar1.ndim)
ar2 = np.array([[1,2,3,4], ['a', 'b', 'c', 'd', 'f']])#两个列表元素个数不一致,此时会变成一维数组
print(ar2, ar2.ndim)
------------------------------------
[['1' '2' '3' '4']  ['a' 'b' 'c' 'd']] 2
[list([1, 2, 3, 4]) list(['a', 'b', 'c', 'd', 'f'])] 1

4. 创建特殊数组

(1)创建值全部为0的数组:zeros(), zeros_like(),
np.zeros(shape, dtype=float, order='C')
np.empty(shape, dtype=float, order='C')

print(np.zeros(10))#创建10个数值为0的一维数组
print(np.empty(10))#创建10个数值为0的一维数组
print(np.zeros((3,5)))#创建15个数值为0的二维数组
print(np.zeros((2,5), dtype=np.int))
--------------------------------------------
[0. 0. 0. 0. 0. 0. 0. 0. 0. 0.]
[0. 0. 0. 0. 0. 0. 0. 0. 0. 0.]
[[0. 0. 0. 0. 0.]
 [0. 0. 0. 0. 0.]
 [0. 0. 0. 0. 0.]]
[[0 0 0 0 0]
 [0 0 0 0 0]]

np.zeros_like(array, dtype=None, order='K', subok=True, shape=None)

ar = np.array([list(range(5)), list(range(6,11))])
print(ar)
print(np.zeros_like(ar))
-------------------------------------
[0. 0. 0. 0. 0. 0. 0. 0. 0. 0.]
[[0. 0. 0.]
 [0. 0. 0.]]
[[ 0  1  2  3  4]
 [ 6  7  8  9 10]]
[[0 0 0 0 0]
 [0 0 0 0 0]]

(2)创建值全部为1的数组:ones(), ones_like()
具体的创建方式与上述创建值全部为0的数组的方式一样
(3)创建一个单位矩阵:eye(),identity()
np.eye(N, M=None, k=0, dtype=, order='C')
np.identity()

print(np.eye(3))
----------------------
[[1. 0. 0.]
 [0. 1. 0.]
 [0. 0. 1.]]

(4)在已有的矩阵外围填充0
np.pad(array, pad_width, mode='constant', **kwargs)

ar = np.arange(9).reshape(3,3)
print(np.pad(ar, pad_width=1))
------------------------------------
[[0 0 0 0 0]
 [0 0 1 2 0]
 [0 3 4 5 0]
 [0 6 7 8 0]
 [0 0 0 0 0]]

(5)生成对角矩阵
np.diag()

ar = np.arange(1,5)
print(np.diag(ar))
---------------------------------
[[1 0 0 0]
 [0 2 0 0]
 [0 0 3 0]
 [0 0 0 4]]

(6)获取数组中非零元素的索引
np.nonzero(array)

lst = [1,2,0,0,4,0]
ar = np.array(lst)
print(np.nonzero(ar))
----------------------------
(array([0, 1, 4], dtype=int64),)

(7)获取N维数组第xx个元素的index
np.unravel_index(indices, shape, order='C')

ar = np.random.randint(15, size=(6,7,8))
print(np.unravel_index(100,(6,7,8)))
---------------------------
(1, 5, 4)

5. Numpy通用函数

(1)数组的形状:array.T, array.reshape(), array.resize
改变数组的形状常用的几个函数有:转置、shape改变、shape与size改变,注意这3个函数都是会生成新的数组,不会改变原始数组
array.T:数组的转置函数

ar = np.array([[1,2,3], ['a', 'b', 'c']])
print(ar)
print(ar.T)
-------------------
[['1' '2' '3']  ['a' 'b' 'c']]
[['1' 'a']  ['2' 'b']  ['3' 'c']]

array.reshape(shape):不会改变原始数组array,而是会生成一个新的数组,所以元素数量需要一致!!
np.reshape(array, shape):使用numpy自带的reshape函数,该函数不会改变原始数组

ar = np.array([[1,2,3, 4, 5], ['a', 'b', 'c', 'd', 'e']])
print(ar)
ar_new = ar.reshape((1,10))
print(ar)
print(ar_new)

print(np.reshape(ar, (1,10)))
print(ar)
--------------------------------
[['1' '2' '3' '4' '5']
 ['a' 'b' 'c' 'd' 'e']]
[['1' '2' '3' '4' '5']
 ['a' 'b' 'c' 'd' 'e']]
[['1' '2' '3' '4' '5' 'a' 'b' 'c' 'd' 'e']]
[['1' '2' '3' '4' '5' 'a' 'b' 'c' 'd' 'e']]
[['1' '2' '3' '4' '5']
 ['a' 'b' 'c' 'd' 'e']]

np.resize(array, new_shape):返回具有指定形状的新数组,如有必要可重复填充所需数量的元素,这点与reshape是不同的
array.resize(new_shape):这种方式会改变原始array的值,通常我们建议用前面一种

print(np.resize(np.arange(5),(2,4)))
ar = np.arange(10)
print(np.resize(ar, (2,6)))
print(ar.resize(2,6))
print(ar)
---------------------------
[[0 1 2 3]
 [4 0 1 2]]
[[0 1 2 3 4 5]
 [6 7 8 9 0 1]]
None
[[0 1 2 3 4 5]
 [6 7 8 9 0 0]]

(2)数组的复制
array.copy():python的赋值逻辑,指向内存中生成的一个值 ,如下ar1和ar2指向同一个值,所以ar1改变,ar2一起改变,因此需要复制函数

ar1 = np.arange(10)
ar2 = ar1
print(ar1 is ar2)
ar3 = ar1.copy()
ar3[2] = 100
print(ar1, ar3)
----------------------
True
[0 1 2 3 4 5 6 7 8 9] [  0   1 100   3   4   5   6   7   8   9]

(3)数组类型转换:array.astype()
array.astype(dtype, order='K', casting='unsafe', subok=True, copy=True)

ar1 = np.arange(10, dtype=float)
ar2 = ar1.astype(np.int64)
print(ar1, ar1.dtype)
print(ar2, ar2.dtype)
--------------------------
[0. 1. 2. 3. 4. 5. 6. 7. 8. 9.] float64
[0 1 2 3 4 5 6 7 8 9] int64

(4)数组的堆叠:np.hstack(), np.vstack(), np.stack()
数组的堆叠函数本质是数组的连接函数,与列表、字典不同的是,数组的连接函数使用的是np.hstack(), np.vstack(), np.stack()
np.hstack(tup):传入的多个数组必须以元组的形式传入,横向连接(按行的方式进行堆叠),此处多个数组的形状必须一样
np.vstack(tup):传入的多个数组必须以元组的形式传入,纵向连接(按列的方式进行堆叠),数组的形状可以不一样

a = np.array([[1], [2], [3]])
b = np.array([['a'], ['b'], ['c']])
print(a)
print(b)
print(np.hstack((a,b)))
print(np.vstack((a,b)))
-------------------------
[[1]
 [2]
 [3]]
[['a']
 ['b']
 ['c']]
[['1' 'a']
 ['2' 'b']
 ['3' 'c']]
[['1']
 ['2']
 ['3']
 ['a']
 ['b']
 ['c']]

np.stack(arrays, axis=0):沿着新轴连接数组的序列,形状必须一样!

  • axis,假设两个数组[1 2 3]和[4 5 6],shape均为(1,3)
  • axis=0:[[1 2 3] [4 5 6]],shape为(2,3),即以行的方式进行堆叠
  • axis=1:[[1 4] [2 5] [3 6]],shape为(3,2),即以列的方式进行堆叠
a = np.arange(5)
b = np.arange(5, 10)
print(np.stack((a,b)))
print(np.stack((a,b), axis=1))
--------------------------------
[[0 1 2 3 4]
 [5 6 7 8 9]]
[[0 5]
 [1 6]
 [2 7]
 [3 8]
 [4 9]]

(5)数组的拆分:np.hsplit(), np.vsplit()
np.hsplit(ary, indices_or_sections):将数组水平(逐列)拆分为多个子数组 ,按列拆分,输出结果为列表,列表中元素为数组
numpy.vsplit(ary, indices_or_sections)::将数组垂直(行方向)拆分为多个子数组,按行拆

ar = np.arange(16).reshape(4,4)
print(ar)
print(np.hsplit(ar, 2))
print(np.vsplit(ar,4))
-------------------------------------
[[ 0  1  2  3]  [ 4  5  6  7]  [ 8  9 10 11]  [12 13 14 15]]
[array([[ 0,  1], [ 4,  5], [ 8,  9], [12, 13]]),  array([[ 2,  3], [ 6,  7], [10, 11], [14, 15]])]
[array([[0, 1, 2, 3]]), array([[4, 5, 6, 7]]), array([[ 8,  9, 10, 11]]), array([[12, 13, 14, 15]])]

(6)数组的简单运算

ar = np.arange(6).reshape(2,3)
print(ar+10)
print(ar * 2)
print(1/(ar+1))
print(ar ** 0.5)#幂次

print(ar.mean())#平均值
print(ar.max())
print(ar.min())
print(ar.std())#标准差
print(ar.var())#方差
print(ar.sum(), np.sum(ar, axis =0))#求和,np.sum() → axis为0,按列求和;axis为1,按行求和
print(np.sort(np.array([1,4,3,2,5,6])))#排序

6. Numpy索引以及切片

(1)基本索引切片
本小节主要介绍一维数组、二维数组与三维数组的索引与切片

  • 一维数组索引与切片:与列表类似
ar = np.arange(20)
print(ar) >>> [ 0  1  2  3  4  5  6  7  8  9 10 11 12 13 14 15 16 17 18 19]
print(ar[4]) >>> 4
print(ar[:3]) >>> [0, 1, 2]
print(ar[::2]) >>> [ 0  2  4  6  8 10 12 14 16 18]
  • 二维数组索引与切片:
ar = np.arange(16).reshape(4, 4)
print(ar)
print(ar[2])#第3行
print(ar[2][2])#第3行第3列
print(ar[1:3])#索引为1-2的行
print(ar[2,2])
print(ar[:2,2:])
---------------------------------------
[[ 0  1  2  3]
 [ 4  5  6  7]
 [ 8  9 10 11]
 [12 13 14 15]]
[ 8  9 10 11]
10
[[ 4  5  6  7]
 [ 8  9 10 11]]
10
[[2 3]
 [6 7]]

如下例子会生成一个类似于棋盘的8*8个网格

ar = np.ones(shape=(8,8))
ar[1::2, ::2] = 0
ar[::2,1::2] = 0
print(ar)
  • 三维数组索引与切片
ar = np.arange(12).reshape(3, 2, 2)
print(ar)
print(ar[2][1])
print(ar[2][1][0])
----------------------------------
[[[ 0  1]
  [ 2  3]]

 [[ 4  5]
  [ 6  7]]

 [[ 8  9]
  [10 11]]]
[10 11]
10

(2)布尔型索引与切片

import numpy as np
ar = np.arange(12).reshape(3,4)
print(ar)
i = np.array([True, False, True])
j = np.array([True, True, False, False])
print(i)
print(j)
print(ar[i])
print(ar[:, j])
print(ar[i, j])
-------------------------------------
[[ 0  1  2  3]
 [ 4  5  6  7]
 [ 8  9 10 11]]
[ True False  True]
[ True  True False False]
[[ 0  1  2  3]
 [ 8  9 10 11]]
[[0 1]
 [4 5]
 [8 9]]
[0 9]

我们可以使用布尔型的矩阵进行数据的筛选

ar = np.arange(12).reshape(3,4)
print(ar>5)  #构造了一个布尔型矩阵
print(ar[ar>5])
--------------------------------------
[[False False False False]
 [False False  True  True]
 [ True  True  True  True]]
[ 6  7  8  9 10 11]

(3)数值索引以及切片值的更改与复制
数值索引与切片值的更改:

ar = np.arange(10)
print(ar)
ar[5] = 100
ar[7:9] = 200
print(ar)
----------------------------------------
[0 1 2 3 4 5 6 7 8 9]
[  0   1   2   3   4 100   6 200 200   9]

数组的复制,与列表类似,如果直接将数组赋值给另一个数组,会造成其中一个数组值的更改影响另一个数组的值。因此数组的复制函数也是有必要的:

ar = np.arange(10)
b = ar.copy()
b[7:9] = 200
print(ar)
print(b)
------------------------------
[0 1 2 3 4 5 6 7 8 9]
[  0   1   2   3   4   5   6 200 200   9]

7. Numpy随机数

numpy.random包含了多种概率分布的随机样本函数,是数据分析的辅助的重点工具之一

(1)随机生成标准正态分布
np.random.normal():normal (Gaussian) distribution,标准正态分布的样本值

sample = np.random.normal(size=(4,4))
print(sample)
-----------------------------------------------
[[-0.19947068  1.08386722 -0.8007086  -0.29973608]
 [-1.4138948   0.11978172  1.1266943  -0.38618087]
 [-2.20107989 -0.03437717 -2.11068913  0.55943784]
 [ 0.01115924 -0.94572094 -0.8717386   1.97596254]]

(2)随机生成[0,1)浮点数
np.random.rand():生成一个[0,1)之间的随机浮点数/N维浮点数组:均匀分布

ar = np.random.rand()
print(ar, type(ar))
print(np.random.rand(4))
print(np.random.rand(2,3))
------------------------------------------
0.39545806581361387 
[0.14330156 0.4138819  0.72934196 0.13847742]
[[0.10330226 0.42875629 0.51752984]
 [0.30286978 0.26096506 0.37244292]]

(3)随机生成一个N维整型数组
np.random.randint(low, high=None, size=None, dtype='l'):生成一个整数/N维整数数组,若high不为None时,取[low, high)之间的随机整数,否则取值[0, low)之间随机整数,且high必须要大于low;dtype参数只能是int类型

print(np.random.randint(3))
print(np.random.randint(2, 10))
print(np.random.randint(10, size=5))
print(np.random.randint(10, size=(2,5)))#生成2行5列的数组,值在[0,10)
print(np.random.randint(10, 50, size=(2,5)))
---------------------------------------------------
1
5
[4 7 7 2 7]
[[2 3 8 6 2]
 [9 8 0 6 2]]
[[16 10 11 26 15]
 [17 11 35 28 44]]

8. Numpy数据的输入与输出

在列表的内容里学习过如何打开文件,进行数据的读写,Numpy也有相应的函数进行数据的读写。主要分为.npy文件与.txt文件的读写
(1).npy文件的存取
对于.npy文件,numpy中可以使用np.save(file, arr, allow_pickle=True, fix_imports=True)进行存储,使用np.load(file, mmap_mode=None, allow_pickle=False, fix_imports=True, encoding='ASCII')函数进行读取
如下例子在桌面上生成一个test.npy,并将数组存入该文件

import os 
os.chdir(r'C:\Users\Bob\Desktop')
ar = np.random.rand(5,5)
print(ar)
np.save('test.npy', ar)
print('finishied')
---------------------------
[[0.06423913 0.75382215 0.56869953 0.98410291 0.39004041]
 [0.26626693 0.41471567 0.33343208 0.44380002 0.85317088]
 [0.97158141 0.64644351 0.03857217 0.81016871 0.8411624 ]
 [0.18725582 0.57724439 0.29543981 0.14655409 0.1001154 ]
 [0.5611382  0.12391804 0.07974878 0.08417997 0.74273726]]
finishied
ar_load = np.load('test.npy')
print(ar_load)
----------------------------
[[0.06423913 0.75382215 0.56869953 0.98410291 0.39004041]
 [0.26626693 0.41471567 0.33343208 0.44380002 0.85317088]
 [0.97158141 0.64644351 0.03857217 0.81016871 0.8411624 ]
 [0.18725582 0.57724439 0.29543981 0.14655409 0.1001154 ]
 [0.5611382  0.12391804 0.07974878 0.08417997 0.74273726]]

(2).txt文件的存取
对于.txt文件,numpy中可以使用np.savetxt()进行存储,使用np.loadtxt()函数进行读取
如下例子在桌面上生成一个test.txt,并将数组存入该文件

ar = np.random.rand(5,5)
print(ar)
np.savetxt('test.txt', ar, delimiter=',', fmt='%.2f') #以逗号分隔开每个元素,存储时保留2为小数点
print('finished')

ar_load = np.loadtxt('test.txt',delimiter=',')
print(ar_load, ar_load.dtype)
----------------------------------------------
[[0.55412062 0.22607233 0.78282203 0.36200306 0.46374254]
 [0.98622828 0.52656624 0.20647287 0.50212248 0.01737296]
 [0.36278898 0.58702447 0.68746675 0.43975599 0.32049743]
 [0.16226933 0.11427889 0.80376318 0.04888106 0.49355556]
 [0.51634686 0.77667928 0.61162141 0.04089656 0.49566949]]
finished
[[0.55 0.23 0.78 0.36 0.46]
 [0.99 0.53 0.21 0.5  0.02]
 [0.36 0.59 0.69 0.44 0.32]
 [0.16 0.11 0.8  0.05 0.49]
 [0.52 0.78 0.61 0.04 0.5 ]] float64

存储到桌面的文件内容为

0.55,0.23,0.78,0.36,0.46
0.99,0.53,0.21,0.50,0.02
0.36,0.59,0.69,0.44,0.32
0.16,0.11,0.80,0.05,0.49
0.52,0.78,0.61,0.04,0.50

你可能感兴趣的:(Numpy)