我有一个程序需要将许多大型的一维numpy浮点数组变成分隔的字符串。相对于我的程序中的数学运算,我发现这个操作相当慢,我想知道是否有办法加速它。例如,考虑以下循环,它在numpy数组中占用100,000个随机数,并将每个数组连接成逗号分隔的字符串。
import numpy as np
x = np.random.randn(100000)
for i in range(100):
",".join(map(str, x))
此循环大约需要20秒才能完成(总计,而不是每个循环)。相反,考虑像元素乘法(x * x)这样的100个循环将花费超过1/10秒完成。显然,字符串连接操作会产生很大的性能瓶颈;在我的实际应用程序中,它将主导整个运行时。这让我想知道,有没有比“,”更快的方式.join(map(str,x))?由于map()是几乎所有处理时间都出现的地方,因此问题在于是否可以更快地将大量数字转换为字符串。
答案 0 :(得分:25)
有点晚了,但这对我来说更快:
#generate an array with strings
x_arrstr = np.char.mod('%f', x)
#combine to a string
x_str = ",".join(x_arrstr)
我的机器加速约1.5倍
答案 1 :(得分:5)
非常好的关于Python中各种字符串连接技术性能的写法:http://www.skymind.com/~ocrow/python_string/
我有点惊讶的是,后面的一些方法表现得和他们一样好,但看起来你肯定能找到一些比你在那里更好的东西。
网站上提到的最快方法
方法6:列表理解
def method6(): return ''.join([`num` for num in xrange(loop_count)])
这种方法最短。我会破坏惊喜并告诉你它 也是最快的。它非常紧凑,也很漂亮 可以理解的。使用列表推导创建数字列表 然后将它们加在一起。不能简单。这个 实际上只是方法4的缩写版本,它消耗了 几乎相同的内存量。它更快,因为我们 不必每次都调用list.append()函数 循环。
答案 2 :(得分:3)
首先将numpy数组转换为列表。地图操作似乎在列表上比在numpy数组上运行得更快。
e.g。
import numpy as np
x = np.random.randn(100000).tolist()
for i in range(100):
",".join(map(str, x))
在时序测试中,我发现此示例的加速率一致为15%
我会留下其他人解释为什么这可能会更快,因为我不知道!
答案 3 :(得分:2)
我认为您可以尝试numpy.savetxt
将cStringIO.StringIO
对象作为假文件传播......
或者可能使用str(x)
并用逗号替换空白(编辑:这不会很好,因为str
执行大数组的省略号:-s)。
由于这个目的是通过网络发送阵列,可能有更好的选择(在cpu和带宽方面更高效)。我在对其他答案的评论中指出的那个将数组的二进制表示编码为Base64文本块。这个最佳的主要不便之处在于,读取数据块的客户端应该能够执行令人讨厌的事情,例如将字节数组重新解释为float数组,而且通常不允许在类型安全的语言中使用;但是可以通过C库调用快速完成(并且大多数语言提供了执行此操作的方法)。
如果你不能乱用比特,总是有可能逐个处理数字,将解码后的字节转换成浮点数。
哦,在通过网络发送数据时注意机器的终端:转换为网络订单 - > base64encode - >发送|接收 - > base64decode - >转换为主机订单
答案 4 :(得分:1)
numpy.savetxt甚至比string.join慢。 ndarray.tofile()似乎不适用于StringIO。
但是我找到了一个更快的方法(至少在python2.5上使用较低版本的numpy应用于OP的例子):
import numpy as np
x = np.random.randn(100000)
for i in range(100):
(",%f"*100000)[1:] % tuple(x)
如果您具有明确定义的格式(例如在此特定情况下),则字符串格式看起来比字符串连接更快。但我想知道为什么OP在内存中需要这么长的浮点数。
较新版本的numpy显示没有速度提升。
答案 5 :(得分:0)
使用来自itertools的imap而不是OP的代码中的map给了我2-3%的改进,这并不是很多,但可能与其他想法相结合以提供更多改进。
就个人而言,我认为如果你想要比这更好,你将不得不使用像Cython这样的东西。
答案 6 :(得分:-1)
','.join(x.astype(str))
比
慢约10%x_arrstr = np.char.mod('%f', x)
x_str = ",".join(x_arrstr)
但更具可读性。