从1d numpy数组生成分隔字符串的最快方法

时间:2010-04-27 13:20:43

标签: python numpy

我有一个程序需要将许多大型的一维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()是几乎所有处理时间都出现的地方,因此问题在于是否可以更快地将大量数字转换为字符串。

7 个答案:

答案 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.savetxtcStringIO.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)

但更具可读性。