Python 从分隔字符串创建scipy.sparse.csr_矩阵

Python 从分隔字符串创建scipy.sparse.csr_矩阵,python,scipy,sparse-matrix,Python,Scipy,Sparse Matrix,我正在处理大量的二进制数据,这些数据以字符串的形式逐行进入我的程序,这些字符串看起来像\t\t1\t\t\t\t,但要长得多。可以想象,这些行来自以制表符分隔的文件 显然,我可以做'\t\t1\t\t1\t\t'.拆分'\t',得到一个1和's的列表,我可以很容易地将其转换为1和0或t/F或其他。但是,数据非常稀疏,很多是0,而不是1,所以我希望使用某种稀疏表示 我的问题是:有没有人知道一种方法可以直接从这个字符串转换为scipy.sparse.csr_矩阵,而不必先创建一个中等密度矩阵 我尝试

我正在处理大量的二进制数据,这些数据以字符串的形式逐行进入我的程序,这些字符串看起来像\t\t1\t\t\t\t,但要长得多。可以想象,这些行来自以制表符分隔的文件

显然,我可以做'\t\t1\t\t1\t\t'.拆分'\t',得到一个1和's的列表,我可以很容易地将其转换为1和0或t/F或其他。但是,数据非常稀疏,很多是0,而不是1,所以我希望使用某种稀疏表示

我的问题是:有没有人知道一种方法可以直接从这个字符串转换为scipy.sparse.csr_矩阵,而不必先创建一个中等密度矩阵

我尝试将拆分字符串(即1和的列表)直接传递给csr_矩阵,但得到了TypeError:不支持类型转换:dtype'scipy无法解释您的输入,因为它不知道您希望将空字符串转换为0。这很好:

>>> from scipy.sparse import csr_matrix
>>> x = [0 if not a else int(a) for a in "\t\t\t\t1\t\t\t1\t\t\t".split('\t')] 
>>> csr_matrix(x)
<1x11 sparse matrix of type '<class 'numpy.int64'>'
        with 2 stored elements in Compressed Sparse Row format>
在创建矩阵之前,确保您的列表都是numbrt格式

根据我回忆的OPs注释,您可以强制将空字符串转换为0,因此更好的解决方案是


这将减少一个列表。

以下是一种逐行处理数据的方法:

In [32]: astr = '\t\t1\t\t1\t\t\t'      # sample row
In [33]: row, col = [],[]
In [34]: for i in range(5):
    ...:     c = [j for j,v in enumerate(astr.split('\t')) if v]
    ...:     row.extend([i]*len(c))
    ...:     col.extend(c)
    ...: data = np.ones(len(col),'int32')
    ...: M = sparse.csr_matrix((data, (row, col)))
    ...: 
In [35]: M
Out[35]: 
<5x5 sparse matrix of type '<class 'numpy.int32'>'
    with 10 stored elements in Compressed Sparse Row format>
In [36]: M.A
Out[36]: 
array([[0, 0, 1, 0, 1],
       [0, 0, 1, 0, 1],
       [0, 0, 1, 0, 1],
       [0, 0, 1, 0, 1],
       [0, 0, 1, 0, 1]], dtype=int32)
获取c值的另一种方法是:

In [46]: np.where(astr.split('\t'))[0]
Out[46]: array([2, 4])
但是列表理解速度更快


字符串和列表查找/索引方法查找第一项,但不是全部。

您是否尝试将s转换为0s,这样scipy就有机会使用int类型?数量有多大?您直接在csr\u矩阵中使用哪种类型的参数?密集阵列?数据、行、列、数据、索引、indptr?换言之,详细说明过去。。。直接转到csr_矩阵,以及为什么您认为它符合函数的文档。对于每一行,您需要确定哪些列具有“1”。由此,您可以构建输入的coo样式。在您的示例中,[2,4]。是的,但这实际上是创建一个包含1和0的稠密矩阵。在本例中,它只是一个稠密向量,但这只是多个向量中的一行。我的问题是我是否可以跳过这一步。换句话说,有没有一种方法可以告诉csr_矩阵,在我的例子中,空字符串代表null或0,或者任何应该稀疏掉的值?@seth127,你的意思是不使用split?不管怎样,这都会迭代你的字符串,你需要迭代它一次吗?@seth127我记得另一种强制数据类型的方法,但是你仍然需要拆分字符串。如果这仍然不是你的意思,你必须澄清。不,我更多地考虑了内存使用和速度,在这个解决方案中,我们有三个对象:字符串、1/0的数组和稀疏矩阵。我试图只得到第一个和第三个对象。你的意思是仅仅通过拆分字符串,我们已经创建了中间的对象,那么为什么不让它成为一个包含1和0的列表呢?请记住,问题是我在这些行中的数亿行上执行此操作,字符串约1k长。这就是为什么我不想要整个东西的3个副本。@seth127什么数组?是的,拆分字符串会在内存中生成一个新列表。在第一个解决方案中,我生成了两个列表,因此第二个更好。这也是一个有趣的选项。你需要把绳子分开吗?是否可以遍历字符串中的字符并用每个'\t'增加列计数?也许这样做效率很低,但我对永远不必拆分或存储0的可能性很感兴趣。
In [40]: c
Out[40]: [2, 4]
In [41]: row
Out[41]: [0, 0, 1, 1, 2, 2, 3, 3, 4, 4]
In [42]: col
Out[42]: [2, 4, 2, 4, 2, 4, 2, 4, 2, 4]
In [43]: data
Out[43]: array([1, 1, 1, 1, 1, 1, 1, 1, 1, 1], dtype=int32)
In [46]: np.where(astr.split('\t'))[0]
Out[46]: array([2, 4])