问题描述
需要一个执行类似于 numpy.where
函数的函数,但不会遇到由布尔数组的密集表示引起的内存问题。因此,该函数应该能够返回一个极其稀疏的布尔数组。
虽然下面给出的示例适用于小数据集/向量,但一旦 numpy.where
是 - 例如 - 形状为 my_sample
和 {{ 1}} 的形状为 (10.000.000,1)
。阅读其他线程后,my_population
显然在评估表达式 (100.000,1)
时创建了一个形状为 numpy.where
的密集布尔数组。这个密集的 (10.000.000,100.000)
数组无法放入我的机器/大多数机器的内存中。
生成的数组非常稀疏。就我而言,知道每行最多有两个 1!使用上述规范,稀疏度等于 0.002%。这绝对应该适合内存。
尝试为数值模拟创建类似于模型/设计矩阵的东西。生成的矩阵将用于一些线性代数运算。
最小工作示例:请注意向量中的位置/坐标很重要。
numpy.where((my_sample == my_population.T))
解决方法
首先,让我们将其编码为整数,而不是字符串。字符串很糟糕。
pop_levels,pop_idx = np.unique(my_population,return_inverse=True)
sample_levels,sample_idx = np.unique(my_sample,return_inverse=True)
pop_levels
和 sample_levels
必须相同,但如果相同,您就大功告成了 - 将它们打包成稀疏掩码:
sample_mask = sps.csr_matrix((np.ones_like(sample_idx),sample_idx,range(len(sample_idx) + 1)))
我们完成了:
>>> sample_mask.A
array([[1,0],[0,1,1],[1,0]])
您可能需要对因子水平重新排序,以使它们在样本和总体之间保持相同,但只要您可以统一这些标签,只需矩阵分配就很容易做到。
,更直接的路线:
In [125]: my_sample = ['a','b','c','a']
...: my_population = ['a','c']
...:
...:
In [126]: np.array(my_sample)[:,None]==np.array(my_population)
Out[126]:
array([[ True,False,False],[False,True,True],[ True,False]])
这是一个布尔数据类型。如果你想要 0/1 整数矩阵:
In [128]: (np.array(my_sample)[:,None]==np.array(my_population)).astype(int)
Out[128]:
array([[1,0]])
如果你有空间来制作my_zero
,你应该有空间来制作这个数组。如果大的临时缓冲区仍然存在问题,您可以尝试转换为'uint8',它占用的空间更少。
在您的版本中,您制作了两个大数组,my_zero
和 my_sample == my_population.T
。但请注意,即使您通过了这一步,您也可能没有空间使用 my_zero
执行任何其他操作。
创建稀疏矩阵可以节省空间,但稀疏度必须非常高才能保持任何速度。尽管矩阵乘法对于 scipy.sparse
矩阵来说是一个相对强大的领域。
时间测试
In [134]: %%timeit
...: pop_levels,return_inverse=True)
...: sample_levels,return_inverse=True)
...: sample_mask = sparse.csr_matrix((np.ones_like(sample_idx),range(len(s
...: ample_idx) + 1)))
247 µs ± 195 ns per loop (mean ± std. dev. of 7 runs,1000 loops each)
In [135]: timeit (np.array(my_sample)[:,None]==np.array(my_population)).astype(int)
9.61 µs ± 9.4 ns per loop (mean ± std. dev. of 7 runs,100000 loops each)
并从密集矩阵中创建一个稀疏矩阵:
In [136]: timeit sparse.csr_matrix((np.array(my_sample)[:,None]==np.array(my_population)).as
...: type(int))
332 µs ± 1.44 µs per loop (mean ± std. dev. of 7 runs,1000 loops each)
大型数组的缩放可能会大不相同。