2012-01-25 16 views
9

Considérese una larga lista de elementos con nombre (primera línea) regresó de un archivo csv grande (80 MB) con una posible separación interrumpidoLista de acceso de artículos con la lista de índices

name_line = ['a',,'b',,'c' .... ,,'cb','cc'] 

Estoy leyendo el resto de la datos en línea por línea y solo necesito procesar datos con un nombre correspondiente. Los datos pueden parecerse a

data_line = ['10',,'.5',,'10289' .... ,,'16.7','0'] 

Lo intenté de dos maneras. Uno está haciendo estallar las columnas vacías de cada línea de la leen

blnk_cols = [1,3, ... ,97] 
while data: 
    ... 
    for index in blnk_cols: data_line.pop(index) 

el otro está recopilando los elementos asociados a un nombre de L1

good_cols = [0,2,4, ... ,98,99] 
while data: 
    ... 
    data_line = [data_line[index] for index in good_cols] 

en los datos que estoy usando definitivamente habrá más buenas líneas y malas líneas, aunque podría ser tan alto como la mitad y la mitad.

Utilicé el paquete cProfile y pstats para determinar mis enlaces más débiles en velocidad, lo que sugería que el pop era el elemento más lento actual. Cambié a la lista de comp y el tiempo casi se duplicó.

Imagino que una forma rápida sería cortar la matriz recuperando solo datos buenos, pero esto sería complicado para los archivos con datos en blanco alternativos y buenos.

lo que realmente necesita es ser capaz de hacer

data_line = data_line[good_cols] 

que pasa efectivamente una lista de índices en una lista para volver a dichos elementos. Ahora mi programa se ejecuta en aproximadamente 2,3 segundos para un archivo de 10 MB y las cuentas pop durante aproximadamente .3 segundos.

¿Hay alguna manera más rápida de acceder a ciertas ubicaciones en una lista? En C, simplemente estaría desreferenciando una matriz de punteros a los índices correctos en la matriz.

Adiciones: name_line en archivo antes de leer

a,b,c,d,e,f,g,,,,,h,i,j,k,,,,l,m,n, 

name_line después de leer y división ("")

['a','b','c','d','e','f','g','','','','','h','i','j','k','','','','l','m','n','\n'] 
+0

¿Qué estás haciendo con data_line? ¿Estás simplemente iterando? ¿Lo estás poniendo en otra estructura de datos? – Marcin

+0

Además, ¿ha probado un generador? – Marcin

+0

"¿Considera la posibilidad de devolver una lista grande de un archivo csv grande? ¿Estás leyendo el ** archivo ** completo en una lista? ¿Por qué? ¿Por qué no procesar cada línea individualmente? –

Respuesta

8

Pruebe una expresión generador,

data_line = (data_line[i] for i in good_cols) 

Lea también aquí acerca de Generator Expressions vs. List Comprehension

como la respuesta superior te dice: 'Básicamente, utiliza una expresión de generador si todo lo que estás haciendo es iterar una vez'.

Así que debería beneficiarse de esto.

+0

Lo que es más rápido, más bien, depende de lo que esté haciendo con él. La ventaja de un generador es que es flojo, por lo que no asigna mucha memoria para los elementos a los que accede solo una vez. – Marcin

+0

@Marcin. Sí, aclaró mi respuesta. –

+0

Refactoré todos mis códigos para adaptarme a las expresiones del generador. Repaso cada línea de datos una vez para procesarla (usando un generador con indexación apropiada en lugar de mostrar los valores en blanco inicialmente). El código se ejecuta aproximadamente 0.3 segundos más lento porque necesito recrear la expresión del generador para cada línea de datos. –

Cuestiones relacionadas