20210211 -
引言
之前的时候,一些关于numpy的内容都记录在另一篇文章中《pandas及numpy - 常用操作》,里面大部分都是pandas的操作,但是最近使用numpy比较多了之后,也积累了一些内容,所以这里专门记录一下。
内容列表
- 拼接空数组
- 距离的计算
- 向量的重复生成
- 数组逆序
- 比较两个浮点数组是否相等
- 输出时指定浮点数小数点位数
- 随机采样(获取索引)
1. 拼接空数组
最近的实验中,需要按照列来拼接相应的结果,但是一开始需要一个空数组来指定,代码逻辑就是创建一个空数组,然后在训练中,按照列来拼接,使用的函数就是np.hstack
。
但是一开始的时候需要创建数组,创建数组的时候,需要注意,一开始我的代码如下:
import numpy as np
tmp_array = np.array([[]])
for i in loop:
tmp_array = np.hstack((tmp_array, xxx[:,i]))
但是这样会提示维度错误。根据[1]中的方法,应该先对这个空数组进行变形,保证维度对应;其提供了两种方法,一种是知道维度,一种是不知道维度。具体代码如下:
1)知道维度:
>>> xs = np.array([[1,2,3,4,5],[10,20,30,40,50]])
>>> ys = np.array([], dtype=np.int64).reshape(0,5)
>>> ys
array([], shape=(0, 5), dtype=int64)
>>> np.vstack([ys, xs])
array([[ 1., 2., 3., 4., 5.],
[ 10., 20., 30., 40., 50.]])
2)不知道维度
>>> ys = np.array([])
>>> ys = np.vstack([ys, xs]) if ys.size else xs
array([[ 1, 2, 3, 4, 5],
[10, 20, 30, 40, 50]])
我的实验中知道数据的维度,使用了第一种方法,第二种方法没有测试。不过,上述代码是为了执行行的拼接,在调整维度的时候需要改变。
2. 距离的计算(向量与矩阵)
正常情况下,如果是按照欧氏距离来进行计算,可以使用自己实现的函数,但实际上已经有现成的库函数来帮助实现,scipy.spatial.distance
,在这个库中,有很多函数帮助实现距离计算:
euclidean() #欧式距离
cosine() #cosine距离
但是上述两个函数都是计算连个一维向量的,如果是比较多维向量和一维向量怎么办,也就是将一个一维向量和矩阵中的每个维度有进行比较。如果是自己实现的话,也可以,当然也可以进行一些向量计算的方式。但是这种方式也是有库的,那就是使用scipy.spatial.distance.cdist
。
使用这种方法的时候,要注意距离类型,以及矩阵和向量的维度,保证维度的统一是关键。在官方文档的示例中:
a = np.array([[0, 0, 0],
[0, 0, 1],
[0, 1, 0],
[0, 1, 1],
[1, 0, 0],
[1, 0, 1],
[1, 1, 0],
[1, 1, 1]])
b = np.array([[ 0.1, 0.2, 0.4]])
distance.cdist(a, b, 'cityblock')
3. 向量的重复生成
一般来说,numpy进行操作的时候,向量的操作也会广播到矩阵上,一般不用使用重复的方法。不过,我这里的需求本质上,是为了生成一个初始化数组,后续会对初始化数组进行完整的操作。
那么这里有两种方法,分别是np.repeat
和np.tile
,在[2]中后面的回答中,好像是说repeat
性能更好。这里的一个需求是,重复行,下面代码展示如何重复10次。
a = np.repeat(np.arange(10).reshape(1,-1), [10], axis = 0)
a
array([[0, 1, 2, 3, 4, 5, 6, 7, 8, 9],
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9],
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9],
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9],
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9],
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9],
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9],
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9],
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9],
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]])
4. 多维数组逆序
一般进行按照数字大小进行排序的话,可以使用np.sort
,如果要逆序的话,可以利用索引方式[::-1]。但是当多维数组的时候,应该怎么办,采用的方法也比较简单,只需要前面添加索引即可[3]:
b = a[:,:,::-1]
5. 比较两个浮点数组是否相等
两个浮点数组,以下为了方便,假设为一维的浮点数组,为了比较两个数组是否完全一致,可以用一下代码:
import numpy
print(numpy.all(x_a == x_b))
但是如果两个数组不是同一种计算方式产生的,哪怕虽然都是浮点数组,他们的小数点很多位之后的不一样,会导致结果为否。这种其实是因为在存储浮点数的时候,不同的计算方式所导致,本质上他们已经非常接近,只不过在内存中有所差距。
这种情况的话,就不能使用这种方法直接比较,而是应该判断是否在一定范围内是否接近。
在文章[4]中对这部分进行了解释,但是这种是针对普通浮点数进行比较的,那么如果是数组的话,可以使用一下代码:
def float_is_close(x_a, x_b, allow_error = 1e-5):
res = np.abs(x_a - x_b)
return np.all(res < allow_error)
6. 输出时指定浮点数小数点位数
在研究前面的内容时,就涉及到具体打印输出来查看结果,而正常情况下,并没有那么多小数点后位数可以查看。在文章[5]中就介绍了这部分的相关代码,具体是通过numpy的行为来控制。
import numpy as np
aa=np.random.rand(2,3)
print(aa)
np.set_printoptions(precision=4)
print(aa)
7. 随机采样数据(获取索引)
有时候要对数据进行采样,平时都是使用pandas的sample方法,直接对DF进行采样,对于标签也在整个数据里面的情况是比较方便的。但是有时候,可能需要处理numpy的情况,特别是将标签和特征分开了,那么就需要在采样的时候获取索引,这样才能保证两个数组采样的结果是一致的。搜索一下找到了解决方案,通过将整个索引来传递到函数中,这样就能获得索引。
number_of_rows = an_array.shape[0]
random_indices = np.random.choice(number_of_rows, size=2, replace=False)
这种方式。
参考
[1]Concatenating empty array in Numpy
[2]“Cloning” row or column vectors
[3]numpy reverse multidimensional array
[4]在python中如何比较两个float类型的数据是否相等
[5]numpy.ndarray类型的数组元素输出时,保留小数点后4位