2011-08-31 9 views
6

br es el nombre de una lista de cadenas que dice así:la conversión de una lista de cadenas en una matriz numpy de una manera más rápida

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

Estoy interesado en las dos primeras columnas, los cuales me gustaría para convertir a una matriz numpy. Hasta el momento, se me ha ocurrido con la siguiente solución:

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

Esto se traduce en tener una matriz 2-D:

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

Sin embargo, desde br es bastante grande (~ 10^5 entradas), este procedimiento lleva algún tiempo. Me preguntaba, ¿hay alguna manera de lograr el mismo resultado, pero en menos tiempo?

Respuesta

4

Esto es mucho más rápido para mí:

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

Cambios:

  • asignar previamente la matriz numpy (esto es grande). Ya sabes que quieres una matriz bidimensional con dimensiones particulares.
  • Solo divide() las primeras 2 columnas, ya que no quieres el resto.
  • No utilice el mapa(): es más lento que las listas de comprensión. Ni siquiera usé listas de comprensión, ya que sabes que solo tienes 2 columnas.
  • Asigne directamente a la matriz preasignada en lugar de generar nuevas matrices temporales a medida que itera.
+4

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

+0

Es bueno saber sobre 'enumerate': no me di cuenta ! También gracias @ steabert a su contribución. Las velocidades de ambas soluciones me parecen bastante similares. – Jir

2

Puede intentar preprocesar (con awk por ejemplo) la lista de cadenas si provienen de un archivo, y usar numpy.fromtxt. Si no puede hacer nada para obtener esta lista, tiene varias posibilidades:

  • renunciar. Ejecutará esta función una vez al día. No le importa la velocidad, y su solución real es lo suficientemente buena
  • escriba un plugin de IO con cython. Usted tiene una gran ganancia potencial porque podrá hacer todos los bucles en c, y afecta directamente los valores en un nudo grande (10^5, 2) ndarray
  • pruebe otro idioma para solucionar su problema. Si el uso de lenguajes como C o Haskell, es posible utilizar ctypes llamar a las funciones compiladas en un DLL de pitón

edición

tal vez este enfoque es ligeramente más rápido:

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

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

¡Me gustó el pensamiento "fuera de la caja"! – Jir

1

cambiando

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

a

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

puede dar lugar a una ligera aceleración. Como solo le importan los primeros dos elementos separados por espacios en cada línea, no es necesario dividir toda la línea. El 2 en i.split(' ',2) dice split para solo hacer un máximo de 2 divisiones. Por ejemplo,

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

¡Gracias por la explicación del segundo argumento de 'split'! – Jir

Cuestiones relacionadas