Python 如何有效地加载稀疏矩阵?
给定具有此结构的文件:Python 如何有效地加载稀疏矩阵?,python,pandas,numpy,scipy,sparse-matrix,Python,Pandas,Numpy,Scipy,Sparse Matrix,给定具有此结构的文件: 单列行是键 键的非零值 例如: abc ef 0.85 kl 0.21 xyz 0.923 cldex plax 0.123 lion -0.831 import numpy as np import pandas as pd from io import StringIO lines = StringIO("""abc ef 0.85 kl 0.21 xyz 0.923 cldex plax 0.123 lion -0.831""") # l
- 单列行是键
- 键的非零值
abc
ef 0.85
kl 0.21
xyz 0.923
cldex
plax 0.123
lion -0.831
import numpy as np
import pandas as pd
from io import StringIO
lines = StringIO("""abc
ef 0.85
kl 0.21
xyz 0.923
cldex
plax 0.123
lion -0.831""")
# load Series
s = pd.read_csv(lines, delim_whitespace=True, header=None, names=['k', 'v'])
s = s.assign(k2=pd.Series(np.where(np.isnan(s.v), s.k, np.nan)).ffill())
result = s[~np.isnan(s.v)].set_index(['k2', 'k']).squeeze()
# convert to sparse matrix (csr)
ss = result.to_sparse()
coo, rows, columns = ss.to_coo(row_levels=['k'], column_levels=['k2'], sort_labels=True)
print(coo.tocsr())
如何创建稀疏矩阵,csr\u矩阵
?
('abc', 'ef') 0.85
('abc', 'kl') 0.21
('abc', 'xyz') 0.923
('cldex', 'plax') 0.123
('cldex', 'lion') -0.31
我试过:
from collections import defaultdict
x = """abc
ef 0.85
kl 0.21
xyz 0.923
cldex
plax 0.123
lion -0.831""".split('\n')
k1 = ''
arr = defaultdict(dict)
for line in x:
line = line.strip().split('\t')
if len(line) == 1:
k1 = line[0]
else:
k2, v = line
v = float(v)
arr[k1][k2] = v
[外]
使用嵌套dict结构不像scipy
稀疏矩阵结构那样方便
有没有办法将上述给定格式的文件轻松读入任何
scipy
稀疏矩阵对象?将@hpaulj的注释转换为答案,您可以迭代添加到行和列索引列表中。稍后,使用pd.factorize
、np.unique
或sklearn
的LabelEncoder
,将其分解为稀疏的coo_矩阵
from scipy import sparse
import numpy as np
import pandas as pd
rows, cols, values = [], [], []
for line in x.splitlines():
if ' ' not in line.strip():
ridx = line
else:
cidx, value = line.strip().split()
rows.append(ridx)
cols.append(cidx)
values.append(value)
rows, rinv = pd.factorize(rows)
cols, cinv = pd.factorize(cols)
sp = sparse.coo_matrix((values, (rows, cols)), dtype=np.float32)
# sp = sparse.csr_matrix((np.array(values, dtype=np.float), (rows, cols)))
如果需要,您可以使用
rinv
和cinv
执行反向映射(将索引转换为字符串)。如果您有dict
dox = {'abc': {'ef': 0.85, 'kl': 0.21, 'xyz': 0.923},'cldex': {'plax': 0.123, 'lion': -0.831}}
这将帮助您将其带到sparsematrix:
indptr = [0]
indices = []
data = []
vocabulary = {}
for d in dox:
for term in dox[d]:
index = vocabulary.setdefault(term, len(vocabulary))
indices.append(index)
data.append(dox[d][term])
indptr.append(len(indices))
mat = csr_matrix((data, indices, indptr), dtype=float)
这利用了scipy的增量矩阵构建。以下是输出:
mat.todense()
目前,在版本0.23中,pandas已经实现了系列和数据帧的稀疏版本。巧合的是,您的数据可以被视为具有多级索引的序列,因此您可以利用这一事实来构建稀疏矩阵。此外,如果格式一致,可以使用几行panda来读取格式,例如:
abc
ef 0.85
kl 0.21
xyz 0.923
cldex
plax 0.123
lion -0.831
import numpy as np
import pandas as pd
from io import StringIO
lines = StringIO("""abc
ef 0.85
kl 0.21
xyz 0.923
cldex
plax 0.123
lion -0.831""")
# load Series
s = pd.read_csv(lines, delim_whitespace=True, header=None, names=['k', 'v'])
s = s.assign(k2=pd.Series(np.where(np.isnan(s.v), s.k, np.nan)).ffill())
result = s[~np.isnan(s.v)].set_index(['k2', 'k']).squeeze()
# convert to sparse matrix (csr)
ss = result.to_sparse()
coo, rows, columns = ss.to_coo(row_levels=['k'], column_levels=['k2'], sort_labels=True)
print(coo.tocsr())
输出
(0, 0) 0.85
(1, 0) 0.21
(2, 1) -0.831
(3, 1) 0.12300000000000001
(4, 0) 0.9229999999999999
该方法不仅返回矩阵,还返回列和行标签,因此还执行反向映射。在上面的示例中,返回以下内容:
['ef', 'kl', 'lion', 'plax', 'xyz']
['abc', 'cldex']
其中,
'ef'
对应于行的索引0
,'abc'
对应于列的索引0
。Scipy稀疏矩阵,所有格式,都有简单的数字索引。因此,第一步是将字符串映射到唯一的数字,例如“abc”=>0、“cldex”=>1、“ef”=>0等。然后创建coo
输入样式-data
,行
,col
。