2011-08-31 46 views
6

br là tên của một danh sách các chuỗi mà đi như thế này:Chuyển đổi một danh sách các chuỗi trong một mảng NumPy một cách nhanh

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

Tôi quan tâm đến hai cột đầu tiên, mà tôi muốn để chuyển đổi thành mảng có nhiều mảng. Cho đến nay, tôi đã đi lên với các giải pháp sau đây:

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

Điều này dẫn vào có một mảng 2-D:

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

Tuy nhiên, vì br là khá lớn (~ 10^5 mục), thủ tục này mất một thời gian. Tôi đã tự hỏi, liệu có cách nào để đạt được kết quả tương tự, nhưng trong thời gian ngắn hơn?

Trả lời

4

Đây là nhanh hơn đáng kể cho tôi:

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]) 

Thay đổi:

  • preallocate mảng NumPy (điều này là rất lớn). Bạn đã biết bạn muốn một mảng 2 chiều với kích thước cụ thể.
  • Chỉ chia() cho 2 cột đầu tiên, vì bạn không muốn phần còn lại.
  • Không sử dụng bản đồ(): nó chậm hơn so với việc hiểu danh sách. Tôi thậm chí không sử dụng tính năng hiểu danh sách, vì bạn biết bạn chỉ có 2 cột.
  • Gán trực tiếp vào mảng được phân bổ thay vì tạo các mảng tạm thời mới khi bạn lặp lại.
+4

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

+0

Tốt để biết về 'liệt kê': Tôi không biết về nó ! Cũng cảm ơn @steabert đến đóng góp của anh ấy. Tốc độ của cả hai giải pháp có vẻ khá giống với tôi. – Jir

2

Bạn có thể thử xử lý trước (với awk cho exemple) danh sách các chuỗi nếu chúng đến từ một tệp và sử dụng numpy.fromtxt. Nếu bạn không thể làm bất cứ điều gì về cách bạn nhận được danh sách này, bạn có một số khả năng:

  • bỏ cuộc. Bạn sẽ chạy chức năng này một lần một ngày. Bạn không quan tâm đến tốc độ và giải pháp thực tế của bạn đủ tốt
  • viết plugin IO với cython. Bạn có tiềm năng lớn vì bạn sẽ có thể thực hiện tất cả các vòng trong c và ảnh hưởng trực tiếp đến các giá trị trong một số lớn (10^5, 2) numpy ndarray
  • thử một ngôn ngữ khác để khắc phục sự cố của bạn. Nếu sử dụng ngôn ngữ như C hoặc Haskell, bạn có thể sử dụng ctypes để gọi các chức năng biên soạn trong một dll từ python

chỉnh sửa

có lẽ phương pháp này là hơi nhanh hơn:

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

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

Đã thích suy nghĩ 'out-of-the-box'! – Jir

1

Thay đổi

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

đến

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

có thể dẫn đến tăng tốc nhẹ. Vì bạn chỉ quan tâm đến hai mục được phân tách bằng dấu cách đầu tiên trong mỗi dòng nên không cần phải tách toàn bộ dòng. 2 trong i.split(' ',2) cho biết split để chỉ tạo tối đa 2 lần chia tách. Ví dụ,

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

Cảm ơn bạn đã giải thích về đối số thứ hai của 'split'! – Jir

Các vấn đề liên quan