回顾
在数据处理利器NumPy初识(三)中,我们介绍了NumPy中对ndarray数据的各种运算以及NumPy中广播机制的基本概念和用法。今天我们来看一下NumPy中随机数的相关内容和对ndarray的存储与加载。
NumPy中的随机数
NumPy中的随机数集中在random包中,它包含了多种概率分布的随机样本,是数据计算、数据分析中的重要辅助工具,主要包括normal(mean,stdev,size)、random(size)、rand(d0, d1, ..., dn)、randn(d0, d1, ..., dn)、randint(low[, high, size, dtype])、choice(a[, size, replace, p])等函数。下面我们分别看一下这几种随机数的用法。
- normal(mean,stdev,size)
normal(mean,stdev,size)生成一组均值为mean,标准差为stdev、大小形状为size的高斯随机数或高斯随机数ndarray。?
import numpy as np arr = np.random.normal(2, 1, size=(5, 5)) print(arr) print("---------------") print(arr.mean()) print("---------------") print(arr.std())
我们创建了一个均值为2,标准差为1的5*5的ndarray,然后使用mean()函数和std()函数分别计算这个ndarray的均值和标准差,虽然由于浮点数误差可能存在偏差,但结果基本上是接近mean=2、std=1的。运行结果如下所示。
- random(size)
random(size)生成一组[0,1)范围(大于等于0小于1)、大小形状为size的随机数或随机数ndarray。此外,random_sample(size)、ranf(size)、sample(size)与random(size)的用法与功能基本一样。?
import numpy as np arr1 = np.random.random(size=(5, 5)) print(arr1) print("---------------") arr2 = np.random.random_sample(size=(5, 5)) print(arr2) print("---------------") arr3 = np.random.ranf(size=(5, 5)) print(arr3) print("---------------") arr4 = np.random.sample(size=(5, 5)) print(arr4)
我们分别用random(size)、random_sample(size)、ranf(size)、sample(size)这四个函数创建5*5的ndarray,可以看到,这四个函数创建的ndarray中的元素都是[0,1)范围内的。运行结果如下所示。
- rand(d0, d1, ..., dn)
rand(d0, d1, ..., dn)生成一个[0, 1)的均匀分布的随机浮点数或N维随机浮点数ndarray,如果没有参数,则返回一个值,如果有参数,则返回d0*d1*…*dn个值。?
import numpy as np x = np.random.rand() print(x) print("---------------") arr = np.random.rand(2, 2, 3) print(arr)
运行结果如下, 当给rand()函数传入参数时,d0, d1, ..., dn分别表示第1、2、...、(n-1)维上的元素个数,会生成一个d0*d1*…*dn的ndarray。
- randn(d0, d1, ..., dn)
randn(d0, d1, ..., dn)生成一个期望为0、方差为1(标准正态分布)的随机浮点数或N维随机浮点数ndarray,参数d0, d1, ..., dn的含义与rand()函数中的参数是一样的。?
import numpy as np x = np.random.randn() print(x) print("---------------") arr = np.random.randn(2, 4, 4) print(arr) print("---------------") print("均值为: " + str(arr.mean())) print("方差为: " + str(arr.var()))
运行结果如下所示,可以看到,虽然存在误差,但是均值和方差分别是解决0和1的。
- randint(low[, high, size, dtype])
randint(low[, high, size, dtype])生成一个整数或N维整数ndarray。当传入参数high时,范围为[low,high),当不传参数high时,范围就会变成为[0,low);size表示生成的ndarray维度大小;dtype为数据类型,但是只能传整型(int、int8、int32、int64等),默认的数据类型是np.int。?
import numpy as np print(np.random.randint(5)) print("---------------") print(np.random.randint(5, 10)) print("---------------") print(np.random.randint(5, size=10)) print("---------------") print(np.random.randint(5, 10, size=(2, 5))) print("---------------") print(np.random.randint(5, dtype=np.int32))
运行结果如下所示。
- choice(a[, size, replace, p])
choice(a[, size, replace, p])生成一个元素值来自数组a、大小形状为size的值或ndarray。a表示输入数组,即生成结果的元素的来源数组,当输入为单个数字例如5时,为range(5);size表示输出的ndarray大小形状,默认为1;replace设置输出数字是否可重复,False代表不可重复,比如a=[1,2,3,4,5],输出的ndarray中1,2,3,4,5不能重复,所以该ndarray的维数不能超过5;p代表a中对应的单位出现的概率,为一个数组,例如[0.1,0.2,0.1,0.3,0.3],他们维数和a相同,且加起来总和必须等于1。?
import numpy as np arr_from = [2, 12, 6, 8, 9] arr1 = np.random.choice(arr_from) print(arr1) print("---------------") arr2 = np.random.choice(arr_from, size=(2, 3)) print(arr2) print("---------------") arr3 = np.random.choice(arr_from, size=(2, 2), replace=False) print(arr3) print("---------------") arr4 = np.random.choice(arr_from, size=(2, 3), p=[0.1, 0.1, 0.1, 0.1, 0.6]) print(arr4) print("---------------") arr_str_from = ['xzq', 'qlh', 'xzq666', 'qlh888'] result = np.random.choice(arr_str_from) print(result)
arr1只传入来源数组a,得到的是一个来自a的值;arr2传入size,返回的结果就会变成指定大小形状的ndarray;arr3将replace参数设置成False,元素不可重复,所以size的大小必须小于源数组a;arr4设置概率p,为了观察差异,我们将最后一个元素9的概率设置成0.6,可以发现,得到的ndarray中出现9的频率会特别高。此外,当源数组a中拥有字符型数据时,整个源数组中的元素都会被转成字符型数据。运行结果如下所示。
- seed(n)
我们在使用随机数时,有时候会有生成相同随机数的需求,NumPy中使用seed()函数来控制生成相同的随机数,每次运行代码时给seed()函数设置相同的标记n时,即可生成相同的随机数。?
import numpy as np # 不使用seed a = np.random.rand(5) print('第一次列表a:',a) a = np.random.rand(5) print('第二次列表a:',a) print("---------------") # 使用seed np.random.seed(2) b = rand(5) print('第一次列表b:',b) np.random.seed(2) b = rand(5) print('第二次列表b:',b) np.random.seed(2) b = rand(5) print('第三次列表b:',b) np.random.seed(0) b = rand(5) print('第四次列表b:',b) np.random.seed(0) b = rand(5) print('第五次列表b:',b) np.random.seed(2) b = rand(5) print('第六次列表b:',b) b = rand(5) print('第七次列表b:',b)
我们通过几组随机数来看一下是否设置seed()函数对生成随机数的影响。运行结果如下所示,可以看到,当不设置seed时,生成的随机数都是随机的不相同的;而使用seed()函数时,对于设置了相同标记的seed(n)时,生成的随机数是一模一样的,如第一次、第二次、第三次、第六次都设置了seed(2),第四次、第五次都设置了seed(0),返回的就分别是一样的随机数,而第七次我们没设置任何seed(),所以又返回了不一样的随机数。
ndarray的存储与加载
NumPy中可以怼ndarray数据进行存储,以便下次继续使用,一般我们将ndarray数据保存成.npy文件。NumPy中使用save()函数对ndarray进行保存,基本用法如下。?
import numpy as np arr = np.random.rand(4, 4) print(arr) np.save('/Users/qhzc-imac-02/Desktop/result.npy', arr) print('保存成功')
运行结果如下所示。我们传入路径和要保存的ndarray,运行后就会在指定路径下生成一个.npy文件。
我们用sublime把这个文件打开,可以看到如下内容。
保存的.npy文件是以二进制格式存储的,所以看到的并不是我们的原始数组。但这不影响我们对保存的数据的继续使用,待下次使用时,只需要使用NumPy中的load()函数即可。?
import numpy as np arr_load = np.load('/Users/qhzc-imac-02/Desktop/result.npy') print(arr_load) print('加载成功')
运行结果如下所示,加载的ndarray就是我们之前保存的ndarray,内容是完全一样的。
如果我们要将多个ndarray保存到同一个文件中,这时我们可以使用NumPy的savez()函数。savez函数的第一个参数是路径,后面的参数则是需要保存的ndarray,有几个传几个,也可以使用关键字参数为ndarray起一个名字,非关键字参数传递的ndarray会自动为传入的数组命名为arr_0,arr_1,arr2等。savez函数保存的是一个.npz压缩文件,其中每个文件都是一个.npy文件,文件名对应于ndarray名。基本用法如下。?
import numpy as np arr1 = np.random.rand(2, 2) arr2 = np.random.rand(3, 3) arr3 = np.random.rand(4, 4) np.savez('/Users/qhzc-imac-02/Desktop/ndarrays_save.npz', arr1, no2=arr2, no3=arr3) print(arr1) print("---------------") print(arr2) print("---------------") print(arr3) print("---------------") print('保存成功')
运行后会在指定路径下生成一个.npz文件,它也是以二进制格式存储的。便于与加载结果的对比将运行结果记录如下。
加载.npz文件同样通过NumPy的load()函数,load()函数会自动识别.npz文件,并且返回一个类似于字典的对象,可以通过ndarray名作为关键字获取ndarray的内容。?
import numpy as np ndarray_dict = np.load('/Users/qhzc-imac-02/Desktop/ndarrays_save.npz') print(ndarray_dict['arr_0']) print("---------------") print(ndarray_dict['no2']) print("---------------") print(ndarray_dict['no3'])
运行结果如下所示。使用时注意保存时给每个ndarray的命名,可以看到,加载出来的数据与保存的是一致的。
以上对ndarray的保存都是以二进制格式保存的,如果我们想从保存的文件中查看我们保存的内容,可以将ndarray保存成.txt格式。NumPy中使用savetxt()函数来存储.txt格式,对应的使用loadtxt()函数来加载.txt文件中的ndarray。?
import numpy as np arr = np.random.rand(4, 4) print(arr) print("---------------") np.savetxt('/Users/qhzc-imac-02/Desktop/ndarray1.txt', arr, delimiter=',') arr_txt_load1 = np.loadtxt('/Users/qhzc-imac-02/Desktop/ndarray1.txt', delimiter=',') print(arr_txt_load1) print("---------------") np.savetxt('/Users/qhzc-imac-02/Desktop/ndarray2.txt', arr, delimiter=',', fmt='%.2f') arr_txt_load2 = np.loadtxt('/Users/qhzc-imac-02/Desktop/ndarray2.txt', delimiter=',') print(arr_txt_load2)
我们创建一个4*4的随机ndarray,分别保存成两个.txt文件,都使用“,”作为分隔符,同时将保存至ndarray2.txt的ndarray设置成保留两位小数。运行后可以看到在指定位置生成了ndarray1.txt和ndarray2.txt两个文件,我们打开这两个文件可以看到如下内容。
ndarray1.txt文件保存的是源数据,而ndarray2.txt文件由于设置了保存两位小数,所以是格式化后的数据。此时再调用loadtxt()函数分别加载这两个.txt文件,就会得到各自文件中的内容。从ndarray1.txt加载的内容与源ndarray一模一样,ndarray2.txt则会加载保留两位小数的ndarray。
总结
以上介绍了NumPy中随机数的基本概念和用法,包括random包下的几个常用相关函数和控制随机数的seed()函数,以及NumPy中对ndarray的存储与加载。感谢大家的关注,欢迎批评指正,一起交流~
?