一种在Python中表示和访问稀疏数据的可扩展方法

时间:2015-11-07 15:30:42

标签: python scalability sparse-matrix

我有一个稀疏的二进制矩阵,用这样的文件表示:

p_1|m_11
p_1|m_12
p_1|m_13
...
p_1|m_1,N1
p_2|m_21
p_2|m_22
...
p_2|m_2,N2
...
p_K|m_K1
...
p_K|m_K,NK

p&{39}和m来自两个相应的集合。如果有K个唯一的pL个唯一的m,则上面代表一个稀疏的K X L矩阵对应于矩阵的单个1元素的行。

p是整数; m是alphanum字符串

我需要对矩阵的各个元素及其行和列进行快速访问。下面显示的当前实现适用于K的小值(L总是大约50,000),但不能扩展。

from scipy import sparse
from numpy import array
import numpy as np

# 1st pass: collect unique ps and ms
Ps = set()
Ms = set()
nnz = 0
with open('data.txt','r') as fin:
    for line in fin:
        parts = line.strip().split('|')
        Ps.add(parts[0])
        Ms.add(parts[1])
        nnz += 1

Ps = list(Ps).sort()    # optional but prefer sorted
Ms = list(Ms).sort()    # optional but prefer sorted
K = len(Ps)
L = len(Ms)

# 2nd pass: create sparse mx
I = np.zeros(nnz)
J = np.zeros(nnz)
V = np.ones(nnz)

ix = 0
with open('data.txt','r') as fin:
    for line in fin:
        parts = line.strip().split('|')
        I[ix] = Ps.index(parts[0])  # TAKES TOO LONG FOR LARGE K
        J[ix] = Ms.index(parts[1])
        ix += 1

data = sparse.coo_matrix((V,(I,J)),shape=(K,L)).tocsr()     

有一种不同的做法可以更好地扩展,但它是什么?

我没有使用稀疏矩阵格式(dict?),我愿意使用任何允许我快速访问的单个元素的数据结构,"行& #34;和"列"

澄清 (我希望)
我试图摆脱使用整数行/列值检索数据的元素,行和列通过搜索两个长字符串数组来提取。

相反,我只想使用实际pm作为键,而不是data[i,j]我希望使用类似data[p_10,m_15]的内容;代替data[i,:]使用类似data[p_10,:]的内容。

我还需要能够从我的数据文件中创建data 快速

再次,data不需要是scipynumpy稀疏矩阵。

1 个答案:

答案 0 :(得分:0)

通过简单地创建两个反向索引,我能够加快下面的第二遍:

from scipy import sparse
from numpy import array
import numpy as np

# 1st pass: collect unique ps and ms
Ps = set()
Ms = set()
nnz = 0
with open('data.txt','r') as fin:
    for line in fin:
        parts = line.strip().split('|')
        Ps.add(parts[0])
        Ms.add(parts[1])
        nnz += 1

Ps = list(Ps).sort()    # optional but prefer sorted
Ms = list(Ms).sort()    # optional but prefer sorted
K = len(Ps)
L = len(Ms)

# create inverse indices for quick lookup
#
mapPs = dict()
for i in range(len(Ps)):
    mapPs[Ps[i]] = i

mapMs = dict()
for i in range(len(Ms)):
    mapMs[Ms[i]] = i

# 2nd pass: create sparse mx
I = np.zeros(nnz)
J = np.zeros(nnz)
V = np.ones(nnz)

ix = 0
with open('data.txt','r') as fin:
    for line in fin:
        parts = line.strip().split('|')
        #I[ix] = Ps.index(parts[0]) # TAKES TOO LONG FOR LARGE K
        #J[ix] = Ms.index(parts[1]) # TAKES TOO LONG FOR LARGE K
        I[ix] = mapPs[parts[0]]
        J[ix] = mapMs[parts[1]]
        ix += 1

data = sparse.coo_matrix((V,(I,J)),shape=(K,L)).tocsr()     

我没有机会在更大的数据集上测试它,但是在我遇到问题的较小数据集上,执行时间从大约1小时到大约10秒!所以我现在对这个解决方案感到满意。