我有一个非常稀疏的矩阵,有~10M行(N)和~1K列(P)。每行只有一个非空值,因此有N个条目。 我还有一个10M非唯一值的数组,这是我想要用它们稀疏矩阵分组的“键”。我们用K表示唯一键的数量(~200K)。
结果应该是具有K行和P列的稀疏矩阵,具有N个条目。
应用pandas groupby函数对我来说性能很差,输出也不稀疏。我试图应用itertools.groupby,但循环花费了太多时间。我想我做错了。
我附上了一个代码来复制我的问题:
import numpy as np
from scipy.sparse import coo_matrix
N = 10000000
P = 1000
K = 200000
keys = np.random.choice(K, N)
row = [i for i in range(N)]
col = np.random.choice(P, N)
data = np.random.normal(loc = 100, scale = 2, size = N)
mat = coo_matrix((data, (row, col)), shape=(N,P))
我将非常感谢一个代码,它将返回一个矩阵/数据帧,其中包含N个条目的维度K X P,键作为索引。
非常感谢! 艾伦
答案 0 :(得分:0)
这看起来像普通矩阵乘法。请注意,由于关键冲突,生成的矩阵将具有少于1000万个非零值。代码的最后一位标识了这些冲突的键,列和多重性:
import numpy as np
from scipy.sparse import coo_matrix
N = 10_000_000
P = 1000
K = 200_000
keys = np.random.choice(K, N)
row = [i for i in range(N)]
col = np.random.choice(P, N)
data = np.random.normal(loc = 100, scale = 2, size = N)
mat = coo_matrix((data, (row, col)), shape=(N,P))
import time
t0 = time.perf_counter()
from scipy import sparse
km = sparse.csc_matrix((np.ones(N,), keys, np.arange(N+1)), (K, N))
result = km @ mat
t1 = time.perf_counter()
print(f'{t1-t0:.3f} seconds')
print(f'{result!r}')
print()
# identify collisions
t0 = time.perf_counter()
idctr = sparse.csr_matrix((np.ones((N,), int), col, np.arange(N+1)), (N, P))
coll = km @ idctr
cidx = *map(np.flatnonzero, map(coll.data.__eq__, range(2, 6))),
c2, c3, c4, c5 = map(np.searchsorted, 4 * (coll.indptr,), cidx, 4 * ('left',))
k2, k3, k4, k5 = map(coll.indices.__getitem__, cidx)
t1 = time.perf_counter()
print(f'{t1-t0:.3f} seconds')
print(', '.join(map(str, map(len, (k2, k3, k4, k5)))), 'collisions of 2, 3, 4, 5 keys')
示例输出:
3.998 seconds
<200000x1000 sparse matrix of type '<class 'numpy.float64'>'
with 9754546 stored elements in Compressed Sparse Column format>
4.110 seconds
237476, 3908, 54, 0 collisions of 2, 3, 4, 5 keys