如何在 python 中有效地从稀疏数组构建字符串
How to build a string out of sparse array efficiently in python
我在 python 中使用 scipy 用于稀疏 arrays/matrices。
我有一个稀疏数组[由其他两个之间的点积生成]。这个数组的大小应该 而不是 很大(可以是数百个)但是这段代码被调用了很多次。所以一定效率很高。
我需要的是一种创建 1 和 0 字符串的有效方法,如下所示:
nonzeros = np.nonzero(hashcode)
arr = ['0']*hashcode_length
if nonzeros != None:
for i in nonzeros[1]:
arr[i] = '1'
concatenated = ''.join(arr)
举个例子...如果稀疏数组的长度为 10 并且值为:
[0, 0, 1, 1, 0, 1, 0, 0, 0, 1]
输出应该是:
"0011010001"
如何改进此代码?
注意:
- 很抱歉没有把所有的代码都放上去,因为它很大而且有太多
不相关的细节
- 如果问题不清楚或有更多细节,请告诉我
需要
我的第一个想法是:
In [1380]: x=sparse.coo_matrix([0,0,1,1,0,1,0,0,0,1])
In [1381]: ''.join([str(i) for i in x.A.ravel().tolist()])
Out[1381]: '0011010001'
不一定更好,但我认为它说明了一些关键问题。使用稀疏矩阵或密集矩阵有用吗?如何将整数转换为字符串?这是 1 行矩阵吗?
我可以使用 astype
改进字符串转换:
In [1393]: ''.join(x.A.ravel().astype('U1'))
Out[1393]: '0011010001'
join
正在对数组执行列表迭代。
对于字节串(PY3,或 PY2 中的普通字符串),tostring
是 join
的替代方法。这只是 returns 作为字符串的数据缓冲区:
In [1451]: x.A.astype('S1').tostring()
Out[1451]: b'0011010001'
我可以在稀疏矩阵上使用 astype
,但是有一个 bug 阻止我做那个密集:
In [1397]: x.astype('U1').A
...
ValueError: unsupported data types in input
=============================
迭代的变体;以 0
字符串开头;把它列成一个清单; sparse.nonzero
只是 returns 来自 coo
格式矩阵的 .col
值。
In [1403]: ll # ll = '0'*x.shape[1]
Out[1403]: '0000000000'
In [1404]: ll=list(ll)
In [1405]: ll
Out[1405]: ['0', '0', '0', '0', '0', '0', '0', '0', '0', '0']
In [1406]: for i in x.col:
...: ll[i]='1'
...:
In [1407]: ll
Out[1407]: ['0', '0', '1', '1', '0', '1', '0', '0', '0', '1']
In [1408]: ''.join(ll)
Out[1408]: '0011010001'
或者用字符串数组做同样的事情:
In [1416]: ll=np.empty(x.shape[1], dtype='U1')
In [1417]: ll.fill('0')
In [1418]: ll
Out[1418]:
array(['0', '0', '0', '0', '0', '0', '0', '0', '0', '0'],
dtype='<U1')
In [1419]: ll[x.col]='1'
In [1420]: ll
Out[1420]:
array(['0', '0', '1', '1', '0', '1', '0', '0', '0', '1'],
dtype='<U1')
这避免了循环,因为我可以一次分配多个值。
对于这个小例子,列表解决方案可能同样快或更快。数组版本有一些数组创建开销,所以如果情况很大,它们是最好的。
即使对于具有 (1,1210) 形状的 coo
矩阵,此列表迭代版本也明显更快:
def foo1(x):
ll=list('0'*x.shape[1]) # ll=['0']*x.shape[1] is little faster
for i in x.col:
ll[i]='1'
return ''.join(ll)
如果矩阵不是 coo
,请转换它,x.tocoo()
或使用 x.nonzero()
(但请查看其代码)。
=========
我忽略了你的 None
测试。为什么在那里?这可能很危险
In [1448]: x.nonzero()[1] != None
/usr/local/bin/ipython3:1: FutureWarning: comparison to `None` will result in an elementwise object comparison in the future.
#!/usr/bin/python3
Out[1448]: True
我在 python 中使用 scipy 用于稀疏 arrays/matrices。
我有一个稀疏数组[由其他两个之间的点积生成]。这个数组的大小应该 而不是 很大(可以是数百个)但是这段代码被调用了很多次。所以一定效率很高。
我需要的是一种创建 1 和 0 字符串的有效方法,如下所示:
nonzeros = np.nonzero(hashcode)
arr = ['0']*hashcode_length
if nonzeros != None:
for i in nonzeros[1]:
arr[i] = '1'
concatenated = ''.join(arr)
举个例子...如果稀疏数组的长度为 10 并且值为:
[0, 0, 1, 1, 0, 1, 0, 0, 0, 1]
输出应该是:
"0011010001"
如何改进此代码?
注意:
- 很抱歉没有把所有的代码都放上去,因为它很大而且有太多 不相关的细节
- 如果问题不清楚或有更多细节,请告诉我 需要
我的第一个想法是:
In [1380]: x=sparse.coo_matrix([0,0,1,1,0,1,0,0,0,1])
In [1381]: ''.join([str(i) for i in x.A.ravel().tolist()])
Out[1381]: '0011010001'
不一定更好,但我认为它说明了一些关键问题。使用稀疏矩阵或密集矩阵有用吗?如何将整数转换为字符串?这是 1 行矩阵吗?
我可以使用 astype
改进字符串转换:
In [1393]: ''.join(x.A.ravel().astype('U1'))
Out[1393]: '0011010001'
join
正在对数组执行列表迭代。
对于字节串(PY3,或 PY2 中的普通字符串),tostring
是 join
的替代方法。这只是 returns 作为字符串的数据缓冲区:
In [1451]: x.A.astype('S1').tostring()
Out[1451]: b'0011010001'
我可以在稀疏矩阵上使用 astype
,但是有一个 bug 阻止我做那个密集:
In [1397]: x.astype('U1').A
...
ValueError: unsupported data types in input
=============================
迭代的变体;以 0
字符串开头;把它列成一个清单; sparse.nonzero
只是 returns 来自 coo
格式矩阵的 .col
值。
In [1403]: ll # ll = '0'*x.shape[1]
Out[1403]: '0000000000'
In [1404]: ll=list(ll)
In [1405]: ll
Out[1405]: ['0', '0', '0', '0', '0', '0', '0', '0', '0', '0']
In [1406]: for i in x.col:
...: ll[i]='1'
...:
In [1407]: ll
Out[1407]: ['0', '0', '1', '1', '0', '1', '0', '0', '0', '1']
In [1408]: ''.join(ll)
Out[1408]: '0011010001'
或者用字符串数组做同样的事情:
In [1416]: ll=np.empty(x.shape[1], dtype='U1')
In [1417]: ll.fill('0')
In [1418]: ll
Out[1418]:
array(['0', '0', '0', '0', '0', '0', '0', '0', '0', '0'],
dtype='<U1')
In [1419]: ll[x.col]='1'
In [1420]: ll
Out[1420]:
array(['0', '0', '1', '1', '0', '1', '0', '0', '0', '1'],
dtype='<U1')
这避免了循环,因为我可以一次分配多个值。
对于这个小例子,列表解决方案可能同样快或更快。数组版本有一些数组创建开销,所以如果情况很大,它们是最好的。
即使对于具有 (1,1210) 形状的 coo
矩阵,此列表迭代版本也明显更快:
def foo1(x):
ll=list('0'*x.shape[1]) # ll=['0']*x.shape[1] is little faster
for i in x.col:
ll[i]='1'
return ''.join(ll)
如果矩阵不是 coo
,请转换它,x.tocoo()
或使用 x.nonzero()
(但请查看其代码)。
=========
我忽略了你的 None
测试。为什么在那里?这可能很危险
In [1448]: x.nonzero()[1] != None
/usr/local/bin/ipython3:1: FutureWarning: comparison to `None` will result in an elementwise object comparison in the future.
#!/usr/bin/python3
Out[1448]: True