2011-08-31 68 views
6

br在numpy的数组转换成字符串列表是一个字符串列表的那个是这样的名字:更快的方式

['14 0.000000 -- (long term 0.000000)\n', 
'19 0.000000 -- (long term 0.000000)\n', 
'22 0.000000 -- (long term 0.000000)\n', 
... 

我感兴趣的是前两列,我想转换为一个numpy数组。 到目前为止,我已经想出以下解决方案:

x = N.array ([0., 0.]) 
for i in br: 
    x = N.vstack ((x, N.array (map (float, i.split()[:2])))) 

这导致成具有2- d数组:

array([[ 0., 0.], 
     [ 14., 0.], 
     [ 19., 0.], 
     [ 22., 0.], 
... 

然而,由于br是相当大的(〜10^5条目),这个过程需要一些时间。 我想知道,有没有办法达到同样的效果,但时间更少?

回答

4

这大大快对我来说:

import numpy as N 

br = ['14 0.000000 -- (long term 0.000000)\n']*50000 
aa = N.zeros((len(br), 2)) 

for i,line in enumerate(br): 
    al, strs = aa[i], line.split(None, 2)[:2] 
    al[0], al[1] = float(strs[0]), float(strs[1]) 

变化:

  • 预分配numpy的数组(这是很大的)。你已经知道你想要一个具有特定维度的二维数组。
  • 只有split()为前2列,因为你不想休息。
  • 不要使用map():它比列表解析速度慢。我甚至没有使用列表解析,因为你知道你只有2列。
  • 直接分配到预分配的数组中,而不是在迭代时生成新的临时数组。
+4

aa = numpy.array([x.split('',2)[0:2] for x in br],dtype ='float') – steabert

+0

很高兴知道'enumerate':我没有意识到它!也感谢@steabert对他的贡献。这两种解决方案的速度看起来与我很相似。 – Jir

2

如果字符串来自文件,您可以尝试进行预处理(以awk为例),并使用numpy.fromtxt。 如果您无法做出任何关于您获得此清单的方式,您有几种可能性:

  • 放弃。您将每天运行一次该功能。你不关心速度,你的实际解决方案已经足够好了
  • 用cython写一个IO插件。你有很大的潜在收益,因为你将能够完成c中的所有循环,并直接影响大(10^5,2)numpy的代理尝试另一种语言来解决你的问题。如果使用的语言,如C或Haskell中,你可以使用ctypes的从蟒蛇

编辑

也许这种方法稍快调用DLL中的编译功能:

def conv(mysrt): 
    return map(float, mystr.split()[:2]) 

br_float = map(conv, br) 
x = N.array(br_float) 
+0

喜欢'开箱即用'的想法! – Jir

1

改变

map (float, i.split()[:2]) 

map (float, i.split(' ',2)[:2]) 

可能会导致轻微的加速。由于您只关心每行中前两个以空格分隔的项目,因此不需要拆分整行。在i.split(' ',2)中的2告诉split只做最多2个分割。例如,

In [11]: x='14 0.000000 -- (long term 0.000000)\n' 

In [12]: x.split() 
Out[12]: ['14', '0.000000', '--', '(long', 'term', '0.000000)'] 

In [13]: x.split(' ',2) 
Out[13]: ['14', '0.000000', '-- (long term 0.000000)\n'] 
+0

感谢解释第二个参数'split'! – Jir