2.NumPy数据储存

本文最后更新于:2022年5月14日 晚上

CSV文件

CSV(Comma-Separated Value,逗号分隔值),CSV是一种常见的文件格式,用来存储批量数据,存储一维、二维数据非常好的格式

将数据写入CSV文件中

np.savetxt(frame,array,fmt='%.18e',delimiter=None)

  • frame:文件、字符串或产生器,可以是.gz或.bz2的压缩文件
  • array:存入文件的数组
  • fmt:写入文件的格式,例如:%d %.2f %.18e
  • delimiter:分割字符串,默认是空格
1
2
3
# 将数据写入CSV文件
a=np.arange(100).reshape(5,20)
np.savetxt('a.csv',a,fmt='%d',delimiter=',')

从CSV文件读取数据

np.loadtxt(frame,dtype=np.float,delimiter=None,unpack=False)

  • frame:文件、字符串或产生器,可以是.gz或.bz2的压缩文件
  • dtype:数据类型,可选
  • delimiter:分割字符串,默认是任何空格
  • unpack:如果True,读入属性将分别写入不同变量
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
32
b=np.loadtxt('a.csv',delimiter=',')

b
Out[10]:
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., 32.,
33., 34., 35., 36., 37., 38., 39.],
[40., 41., 42., 43., 44., 45., 46., 47., 48., 49., 50., 51., 52.,
53., 54., 55., 56., 57., 58., 59.],
[60., 61., 62., 63., 64., 65., 66., 67., 68., 69., 70., 71., 72.,
73., 74., 75., 76., 77., 78., 79.],
[80., 81., 82., 83., 84., 85., 86., 87., 88., 89., 90., 91., 92.,
93., 94., 95., 96., 97., 98., 99.]])



b=np.loadtxt('a.csv',dtype=np.int,delimiter=',') # 规定整数类型

b
Out[16]:
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, 32, 33, 34, 35,
36, 37, 38, 39],
[40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55,
56, 57, 58, 59],
[60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75,
76, 77, 78, 79],
[80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95,
96, 97, 98, 99]])

CSV文件的局限性

CSV格式只能有效存储一维和二维数组

多维数组的存取

NumPy提供了一些方法来存取多维数据

a.tofile(frame,sep='',for,at='%s')

  • frame:文件、字符串
  • sep:数据分割字符串,如果是空串,写入文件为二进制
  • format:写入数据的格式。
1
2
a=np.arange(100).reshape(5,10,2)
a.tofile("b.dat",sep=",",format='%d')

如果不指定sep值,文件会使用二进制存储,占用的空间会更小,所以适合给数据备份

np.fromfile(frame,dtype=float,count=-1,sep='')

  • frame:文件、字符串
  • dtype:读取的数据类型,默认为float。
  • count:读入元素的个数,-1表示读入整个文件
  • sep:数据分割字符串,如果为空串,写入文件为二进制
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
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
a=np.arange(100).reshape(5,10,2)
a.tofile("b.dat",sep=",",format="%d")

c=np.fromfile("b.dat",dtype=np.int,sep=",") # 写入文件后,数据的维度信息会丢失

c
Out[22]:
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, 32, 33,
34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50,
51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67,
68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84,
85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99])

c=np.fromfile("b.dat",dtype=np.int,sep=",").reshape(5,10,2) # 要重新指定维度信息,还原文件

c
Out[24]:
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],
[32, 33],
[34, 35],
[36, 37],
[38, 39]],

[[40, 41],
[42, 43],
[44, 45],
[46, 47],
[48, 49],
[50, 51],
[52, 53],
[54, 55],
[56, 57],
[58, 59]],

[[60, 61],
[62, 63],
[64, 65],
[66, 67],
[68, 69],
[70, 71],
[72, 73],
[74, 75],
[76, 77],
[78, 79]],

[[80, 81],
[82, 83],
[84, 85],
[86, 87],
[88, 89],
[90, 91],
[92, 93],
[94, 95],
[96, 97],
[98, 99]]])

注意:该NumPy库提供的存取高维数据的方法,需要在读取时知道存入文件数组的维度和元素类型,a.tofile()np.fromfile()要配合使用。

可以通过元数据文件来存储额外的信息,在读取数据时先读取元数据,根据元数据的信息,将文件数据还原。

NumPy的便捷文件存取

np.save(fname,array)np.savez(fname,array)

  • frame:文件名,以.npy为扩展名,压缩扩展名为.npz
  • array:数组变量

np.load(fname)

  • frame:文件名,以.npy为扩展名,压缩扩展名为.npz
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
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
a=np.arange(100).reshape(5,10,2)

np.save("a.npy",a) # 使用save和load方法可以储存数据的维度,不需要再读取的时候指定维度信息。

b=np.load("a.npy")

b
Out[28]:
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],
[32, 33],
[34, 35],
[36, 37],
[38, 39]],

[[40, 41],
[42, 43],
[44, 45],
[46, 47],
[48, 49],
[50, 51],
[52, 53],
[54, 55],
[56, 57],
[58, 59]],

[[60, 61],
[62, 63],
[64, 65],
[66, 67],
[68, 69],
[70, 71],
[72, 73],
[74, 75],
[76, 77],
[78, 79]],

[[80, 81],
[82, 83],
[84, 85],
[86, 87],
[88, 89],
[90, 91],
[92, 93],
[94, 95],
[96, 97],
[98, 99]]])

.npy文件能够保留维度信息,是因为.npy文件会再第一行写入数组的元数据,读取时,就能根据元数据还原维度信息。

NumPy的随机函数

NumPy也有提供随机数功能的random子库,与python的标准库random库不同,random库只能给标量提供随机数,而NumPy的random能给数组提供随机数。

可以通过np.random.(name),来使用NumPy的random库函数。

函数说明
rand(d0,d1,...,dn)根据d0-dn创建随机数数组,浮点数,[0,1),均匀分布
randn(d0,d1,...,dn)根据d0-dn创建随机数数组,标准正态分布
randint(low,high,(shape))根据shape创建随机整数或整数数组,范围是[low,high]
seed(s)随机数种子,s是给定的种子值
shuffle(a)根据数组a的第1轴进行随机排列,改变数组x
permutation(a)根据数组a的第1轴产生一个新的乱序数组,不改变数组x
choice(a,(size),replace,p)从一维数组a中以概率p抽取元素,形成size形状新数组,replace表示已选取的元素是否可以重用
uniform(low,high,size)产生具有均匀分布的数组,low起始值,high结束值,size形状
normal(loc,scale,size)产生具有正态分布的数组,loc均值,scale标准差,size形状
poisson(lam,sizze)产生具有泊松分布的数组,lam随机事件发生率,size形状
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
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
a=np.random.rand(3,4,5)  # 随机生成0-1之间的浮点数

a
Out[30]:
array([[[0.26674228, 0.62874947, 0.1355554 , 0.79577266, 0.04205209],
[0.76391386, 0.35645442, 0.46574881, 0.93997666, 0.68118593],
[0.52823144, 0.19316118, 0.85955821, 0.89488413, 0.83290191],
[0.689588 , 0.49177381, 0.74969038, 0.93357638, 0.60896234]],

[[0.48745268, 0.70430119, 0.47039112, 0.29423975, 0.75241304],
[0.49073194, 0.51965193, 0.11574008, 0.26220681, 0.83485787],
[0.9994019 , 0.92758344, 0.41835292, 0.27664515, 0.40022266],
[0.53859049, 0.41986168, 0.06510878, 0.80029957, 0.49763107]],

[[0.73485545, 0.59243499, 0.50266137, 0.11972348, 0.64405263],
[0.96879874, 0.42520945, 0.67983068, 0.81248124, 0.30157164],
[0.64786945, 0.20235209, 0.86772226, 0.69899595, 0.60491741],
[0.96194679, 0.47814241, 0.77908961, 0.10318829, 0.1427704 ]]])

sn=np.random.randn(3,4,5) # 生成符合正态分布的随机数

sn
Out[32]:
array([[[-5.81787166e-01, -7.95545001e-01, 7.58131198e-01,
7.02675038e-01, -3.99655474e-02],
[-1.82935062e+00, -1.40149772e+00, -8.78156574e-01,
-2.48930188e+00, 1.90155856e+00],
[ 1.54334791e-01, 3.38971138e-01, -9.64586774e-02,
-6.25083045e-01, 5.68999251e-01],
[ 3.79832062e-01, -8.69108542e-01, 2.94651561e+00,
-4.44543470e-01, 7.59509157e-01]],

[[-1.27399015e+00, -6.22312336e-01, 1.02604546e+00,
1.96754100e-01, 9.34364918e-02],
[-9.59257898e-02, -1.23283945e-01, 3.96693420e-01,
-1.50122710e+00, -5.78568508e-01],
[ 1.78444628e-01, 8.93795761e-02, 2.69073589e-01,
1.06058671e+00, 2.30005162e-03],
[ 4.11105101e-02, 1.47711465e+00, -1.24698994e+00,
-1.53041437e+00, 1.01971779e+00]],

[[-1.32928711e+00, 1.10958199e-01, -1.17783746e+00,
-1.32694638e+00, -9.02942540e-01],
[-1.45098912e+00, 1.27819247e+00, -1.06249801e+00,
7.28906783e-01, -1.72252082e-01],
[ 6.42886398e-01, -6.43561668e-01, -1.34048932e+00,
-1.25799661e+00, 2.86085419e-01],
[-2.76794328e-01, -1.52621299e+00, 1.54399434e+00,
-2.29748374e-01, -2.25366340e+00]]])

b=np.random.randint(100,200,(3,4)) # 生成在100-200之间大的,符合3x4形状的随机数组

b
Out[34]:
array([[162, 179, 106, 177],
[156, 196, 165, 152],
[136, 121, 107, 108]])

np.random.seed(5) # 设定随机种子,再次调用随机数种子生成随机数组时会生成一样的数组

np.random.randint(100,200,(3,4))
Out[38]:
array([[199, 178, 161, 116],
[173, 108, 162, 127],
[130, 180, 107, 176]])

np.random.randint(100,200,(3,4))
Out[39]:
array([[115, 153, 180, 127],
[144, 177, 175, 165],
[147, 130, 184, 186]])


np.random.seed(5)

np.random.randint(100,200,(3,4))
Out[41]:
array([[199, 178, 161, 116],
[173, 108, 162, 127],
[130, 180, 107, 176]])


a=np.random.randint(100,200,(3,4)) # shuffle会根据第一轴随机排列,并改变原来的数组a,而permutation函数不会改变原来的数组

a
Out[44]:
array([[115, 153, 180, 127],
[144, 177, 175, 165],
[147, 130, 184, 186]])

np.random.shuffle(a)

a
Out[46]:
array([[147, 130, 184, 186],
[115, 153, 180, 127],
[144, 177, 175, 165]])
b=np.random.randint(100,200,(8,)) # 生成8个元素的一维数组

b
Out[48]: array([109, 141, 162, 101, 182, 116, 178, 105])

np.random.choice(b,(3,2)) # 将b数组变成3x2的数组,元素可重用
Out[49]:
array([[162, 109],
[109, 182],
[178, 182]])

np.random.choice(b,(3,2),replace=False) # replace让元素不可重用
Out[50]:
array([[116, 105],
[182, 109],
[162, 178]])

np.random.choice(b,(3,2),p=b/np.sum(b)) # 为元素抽取赋予概率,这里元素的值越大则抽取概率越高
Out[51]:
array([[182, 116],
[178, 182],
[182, 162]])


u=np.random.uniform(0,10,(3,4)) # 均匀的从0-10的范围内抽取数字,产生3x4的数组

u
Out[54]:
array([[6.90931197, 8.1616768 , 9.25643489, 0.05735057],
[7.20559573, 6.67059137, 1.99765406, 6.96664929],
[5.75413707, 5.79721399, 0.64506899, 1.7724613 ]])

n=np.random.normal(10,5,(3,4)) # 以10为均值,5为标准差生成具有正态分布特征的3x4数组。围绕某一均值在特定方差下,随机变量取值的空间概率

n
Out[56]:
array([[15.5313291 , 1.93610848, 8.67560705, 8.93431315],
[ 9.07845883, 12.11921961, 6.38469157, 9.78790321],
[ 5.46196987, 6.27937203, 9.22652647, 12.7923338 ]])

NumPy的统计函数

NumPy的统计函数可以对数组进行统计。

使用np.name调用统计函数

NumPy的常用统计函数:

函数说明
sum(a,axis=None)根据给定轴axis计算数组a相关元素之和,axis整数或元组
mean(a,axis=None)根据给定轴axis计算数组a相关元素的期望,也就是算术平均值,axis整数或元组
average(a,axis=None,weights=None)根据给定轴axis计算数组a相关元素的加权平均值(权就是一个数据出现的次数55)
std(a,axis=None)根据给定轴axis计算数组a相关元素的标准差
var(a,axis=None)根据给定轴axis计算数组a相关元素的方差
min(a) max(a)计算数组a中元素的最小值、最大值
argmin(a) argmax(a)计算数组a中元素最小值、最大值的降一维后下标
unravel_index(index,shape)根据shape将一维下标index转换成多维下标
ptp(a)计算数组a中元素最大值与最小值的差
median(a)计算数组a中元素的中位数(中值)
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
32
33
34
35
36
37
38
39
40
41
42
43
44
a=np.arange(15).reshape(3,5)

a
Out[58]:
array([[ 0, 1, 2, 3, 4],
[ 5, 6, 7, 8, 9],
[10, 11, 12, 13, 14]])

np.sum(a) # 对所有元素求和
Out[59]: 105

np.mean(a,axis=1) # 对第二个维度求算术平均值
Out[60]: array([ 2., 7., 12.])

np.mean(a,axis=0) # 对第一个维度求算术平均值
Out[62]: array([5., 6., 7., 8., 9.])

np.average(a,axis=0,weights=[10,5,1]) # 对第一个维度求加权平均值,三个维度的权值分别是10,5,1
Out[63]: array([2.1875, 3.1875, 4.1875, 5.1875, 6.1875])
# 以4.1875为例,2*10+7*5+1*12/(10+5+1)=4.1875


b=np.arange(15,0,-1).reshape(3,5)

b
Out[66]:
array([[15, 14, 13, 12, 11],
[10, 9, 8, 7, 6],
[ 5, 4, 3, 2, 1]])

np.max(b) # 返回数组b的最大值
Out[67]: 15

np.argmax(b) # 返回数组b的最大值的一维下标
Out[68]: 0

np.unravel_index(np.argmax(b),b.shape) # 将数组b最大值的一维下标转换为多维下标
Out[69]: (0, 0)

np.ptp(b) # 计算数组b的最大值与最小值之差
Out[70]: 14

np.median(b) # 计算数组b的中位数
Out[71]: 8.0

NumPy的梯度函数

np.gradient(f):计算数组f中元素的梯度,当f为多维时,返回每个维度的梯度。

梯度:连续值之间的变化率,即斜率。例如:

XY坐标轴连续三个x坐标对应的Y轴值:a,b,c,其中,b的梯度是:(c-a)/2

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
a=np.random.randint(0,20,(5))

a
Out[73]: array([ 8, 12, 5, 11, 5])

np.gradient(a) # 计算每个元素的梯度值,例如12,用(5-8)/2=-1.5,对于两端的用后面的数减前面的数除以1,例如5,用(5-11)/1=-6
Out[74]: array([ 4. , -1.5, -0.5, 0. , -6. ])

# 计算二维数组的梯度值
c=np.random.randint(0,50,(3,5))

c
Out[76]:
array([[41, 22, 5, 18, 27],
[29, 24, 33, 28, 15],
[ 6, 35, 47, 20, 49]])

np.gradient(c)
Out[77]:
[array([[-12. , 2. , 28. , 10. , -12. ], # 第一个数组表示最外层维度的梯度
[-17.5, 6.5, 21. , 1. , 11. ],
[-23. , 11. , 14. , -8. , 34. ]]),
array([[-19. , -18. , -2. , 11. , 9. ], # 第二个数组表示第二层维度的梯度
[ -5. , 2. , 2. , -9. , -13. ],
[ 29. , 20.5, -7.5, 1. , 29. ]])]

梯度反映了元素的变化率,在进行图像和声音处理的时候,梯度有助于发现图像的边缘