2011-08-31 69 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