我需要存储稀疏矩阵数据。
数据大小为10^6 10^4
列。
在每一列中,我存储一个0的向量,除了少量的值true
。
然后我需要对每个矩阵中的列求和,并将每一行乘以标量。 我试过字典,但是当我需要求和时,它们会失败。
你会用什么?
PS。 numpy.zeros太小了
答案 0 :(得分:4)
两句话怎么样?假设这是矩阵(x
的{{1}}):
True
您只需要存储
0 1 2 3 4 5 6 7
0 x x x
1 x
2 x
3 x
4
5
6 x x
7
您可以轻松将其转换为
rows = {0: [0, 2, 5], 1: [1], 2: [7], 3: [4], 6: [2, 5]}
使用
之类的东西columns = {0: [0], 1: [1], 2: [0, 6], 4: [3], 5: [0, 6], 7: [2]}
然后对列(columns = {}
for row in rows:
for column in rows[row]:
columns.setdefault(column, []).append(row)
)或行进行求和,并将结果乘以您想要的任何值。
答案 1 :(得分:2)
正如其他人所说,你应该看看scipy.sparse
:
http://docs.scipy.org/doc/scipy/reference/sparse.html
有许多不同的格式针对各种稀疏操作进行了优化,包括标量乘法和求和。
例如:
import scipy.sparse
import numpy as np
rows = np.array([1,100,1000])
cols = np.array([100,99,1474])
vals = np.ones_like(rows)
A = scipy.sparse.coo_matrix((vals,(rows,cols)),shape=(int(1E6),int(1E6)),dtype=np.bool)
然后乘以标量并取总和:
B = 3*A
B.sum() # 9
答案 2 :(得分:1)
根据您的需要,有数百种方法可以做到这一点。维基百科上的Sparse Matrix条目是一个很好的开端,可以找到一种特别适合您需求的方法。
作为一个非常简单的示例,您可以使用Dictionary of Keys类,如下所示:
class SparseDOK(dict):
def __init__(self):
pass
def __setitem__(self,key,value):
if value in[0,0.0,False,None]:
dict.__setitem__(self,key,False)
dict.__delitem__(self,key)
else:
dict.__setitem__(self,key,True)
def __getitem__(self, key):
try:
return dict.__getitem__(self, key)
except KeyError:
return False
>>> dok=SparseDOK()
>>> dok[10,20]=55
>>> print dok
{(10, 20): True}
>>> print dok[10,20]
True
>>> print dok[55,300]
False
>>> dok[10,20]=False
>>> print dok[10,20]
False
任意“矩阵”中的每个条目都假定为False,除非特别设置为True。您需要添加错误检查,但这将非常紧凑和快速。
构建Key of Dictionary的优点是非常有效地构建数据结构。您只需要浏览一次原始数据,就可以轻松添加或删除数据。缺点是,一旦构建了矩阵,就会减少对矩阵的交互处理。
由于字典键是元组,因此按行或列添加索引是微不足道的。由于整个矩阵需要在构造之后进行处理才能执行此操作,我们可以构造一个dict,其中包含一次所需的总和或产品,然后参考已处理数据的dict。
>>> dok[10,20]=True
>>> dok[10,2000]=True
>>> dok[11,2000]=True
>>> dok[35000,2000]=True
>>> dok[10,35000]=True
>>> print dok
{(11, 2000): True, (10, 2000): True, (35000, 2000): True, (10, 20): True, (10, 35000): True}
cols={}
for tup in dok.keys():
if tup[1] not in cols:
cols[tup[1]]=1
else:
cols[tup[1]]+=1
>>> print cols
{2000: 3, 35000: 1, 20: 1}
现在,您可以在cols
中引用col键来获取行的总和。添加产品等是微不足道的。请记住,如果编辑或更改原始DOK,则需要重新计算总和/产品。如果您预计DOK在首次创建后会经常更改,则可以保持运行总计。
如果您的需求更复杂,请考虑使用SciPy或Pysparse。如您所见,SciPy中有7种不同的稀疏矩阵格式。不要重新发明别人已经做得更好的事情......