2012-01-25 17 views
9

Rozważmy dużą listę nazwanych przedmiotów (pierwsza linia) powrócił z dużego pliku csv (80 MB) z możliwością przerwania rozstawieLista dostępu przedmiotów z listy indeksów

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

Czytam pozostałej części dane w linii po linii i muszę tylko przetwarzać dane o odpowiedniej nazwie. Dane mogą wyglądać tak, jakby:

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

Próbowałem go na dwa sposoby. Jednym z nich jest popping pustych kolumn z każdego wiersza odczytu

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

drugi jest kompilacji przedmioty związane z nazwą z L1

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

w danych używam na pewno będzie więcej dobrego linie to złe linie, choć może być tak wysokie, jak połowa i połowa.

Użyłem pakietu cProfile i pstats, aby określić moje najsłabsze ogniwa prędkości, które sugerowały, że pop był aktualnie najwolniejszym przedmiotem. Przełączyłem się na kompilację listy, a czas prawie się podwoił.

Wyobrażam sobie, że jednym szybkim sposobem byłoby przecięcie tablicy pobierającej tylko dobre dane, ale byłoby to skomplikowane dla plików z naprzemiennymi pustymi i dobrymi danymi.

czego naprawdę potrzebujemy, aby móc zrobić

data_line = data_line[good_cols] 

skutecznie przekazując listę indeksów na listę wrócić te elementy. Obecnie mój program działa w około 2,3 sekundy dla pliku 10 MB, a konta pop przez około 0,3 sekundy.

Czy istnieje szybszy sposób dostępu do określonych lokalizacji na liście. W C będzie to po prostu odwołanie tablicy wskaźników do poprawnych indeksów w tablicy.

Dodatki: name_line w pliku przed odczytać

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

name_line po czytać i split ("")

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

Co robisz z data_line? Czy to tylko iteracja? Czy umieszczasz go w innej strukturze? – Marcin

+0

Czy próbowałeś też generatora? – Marcin

+0

"Zastanów się nad dużą listą zwróconą z dużego pliku CSV"? Czy czytasz ** cały ** plik na jednej liście? Czemu? Dlaczego nie przetworzyć każdej linii indywidualnie? –

Odpowiedz

8

Spróbuj wyrażenie Generator,

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

Przeczytaj także tutaj o Generator Expressions vs. List Comprehension

jako górna odpowiedź mówi: "Zasadniczo użyj wyrażenia generatora, jeśli wszystko co robisz to iterowanie raz".

Powinieneś z tego skorzystać.

+0

Co jest szybsze, zależy raczej od tego, co robisz z tym. Zaletą generatora jest to, że jest on leniwy, więc nie przydzielasz dużo pamięci dla przedmiotów, do których masz dostęp tylko raz. – Marcin

+0

@Marcin. Tak, wyjaśniłem moją odpowiedź. –

+0

Refaktoryzowałem cały mój kod, aby pasował do wyrażeń generatora. Każdą linię danych przechodzę raz, aby przetworzyć (za pomocą generatora z odpowiednim indeksowaniem zamiast początkowo wstawiać puste wartości). Kod działa wolniej o .3 sekundy, ponieważ muszę odtworzyć wyrażenie generujące dla każdej linii danych. –

Powiązane problemy