2013-08-15 9 views
20

Wysłałem to pytanie, ponieważ zastanawiałem się, czy zrobiłem coś strasznie złego, aby uzyskać ten wynik.Numpy ładowanie csv Zbyt powolne w porównaniu do Matlab

Mam plik CSV średniej wielkości i próbowałem użyć numpy do załadowania pliku. Dla ilustracji, zrobiłem plik przy użyciu Pythona:

import timeit 
import numpy as np 

my_data = np.random.rand(1500000, 3)*10 
np.savetxt('./test.csv', my_data, delimiter=',', fmt='%.2f') 

A potem próbowałem dwie metody: numpy.genfromtxt, numpy.loadtxt

setup_stmt = 'import numpy as np' 
stmt1 = """\ 
my_data = np.genfromtxt('./test.csv', delimiter=',') 
""" 
stmt2 = """\ 
my_data = np.loadtxt('./test.csv', delimiter=',') 
""" 

t1 = timeit.timeit(stmt=stmt1, setup=setup_stmt, number=3) 
t2 = timeit.timeit(stmt=stmt2, setup=setup_stmt, number=3) 

A wynik pokazuje, że t1 = 32,159652940464184, t2 = 52.00093725634724.
Jednak, gdy próbowałem za pomocą Matlaba:

tic 
for i = 1:3 
    my_data = dlmread('./test.csv'); 
end 
toc 

Wynik pokazuje: Czas jest 3,196465 sekundy.

Rozumiem, że mogą występować pewne różnice w szybkości ładowania, ale:

  1. Jest to o wiele więcej niż się spodziewałem;
  2. Czy to nie jest tak, że plik np.loadtxt powinien być szybszy niż np.genfromtxt?
  3. Nie próbowałem jeszcze modułu Pythona csv, ponieważ ładowanie pliku csv jest naprawdę częstą czynnością, którą robię, a także z modułem CSV, kodowanie jest trochę pełne gadek ... Ale z chęcią wypróbuję, jeśli to jest jedyny sposób. Obecnie jestem bardziej zaniepokojony tym, czy robię coś złego.

Wszelkie dane wejściowe będą mile widziane. Z góry dziękuję!

Odpowiedz

32

Tak, czytanie csv pliki do numpy jest dość powolne. Na ścieżce kodu jest dużo czystego Pythona. Te dni, nawet gdy używam czystej numpy nadal korzystać pandas do IO:

>>> import numpy as np, pandas as pd 
>>> %time d = np.genfromtxt("./test.csv", delimiter=",") 
CPU times: user 14.5 s, sys: 396 ms, total: 14.9 s 
Wall time: 14.9 s 
>>> %time d = np.loadtxt("./test.csv", delimiter=",") 
CPU times: user 25.7 s, sys: 28 ms, total: 25.8 s 
Wall time: 25.8 s 
>>> %time d = pd.read_csv("./test.csv", delimiter=",").values 
CPU times: user 740 ms, sys: 36 ms, total: 776 ms 
Wall time: 780 ms 

Alternatywnie, w dość proste sprawy jak ten, można użyć coś co Joe Kington napisał here:

>>> %time data = iter_loadtxt("test.csv") 
CPU times: user 2.84 s, sys: 24 ms, total: 2.86 s 
Wall time: 2.86 s 

jest też textreader biblioteka Warrena Weckesser jest w przypadku pandas jest zbyt ciężki zależność:

>>> import textreader 
>>> %time d = textreader.readrows("test.csv", float, ",") 
readrows: numrows = 1500000 
CPU times: user 1.3 s, sys: 40 ms, total: 1.34 s 
Wall time: 1.34 s 
+0

Dziękuję bardzo! Pd.read_csv działa doskonale dla mnie - w rzeczywistości skończyło się tylko w połowie czasu, który zajęło MATLAB! A także dzięki za dwie inne bardzo pouczające metody o mniejszej wadze. –

4

Jeśli chcesz po prostu zapisać i odczytać tablicę numpy jej znacznie lepiej, aby zapisać go jako plik binarny binarny lub sprężonego w zależności od rozmiaru:

my_data = np.random.rand(1500000, 3)*10 
np.savetxt('./test.csv', my_data, delimiter=',', fmt='%.2f') 
np.save('./testy', my_data) 
np.savez('./testz', my_data) 
del my_data 

setup_stmt = 'import numpy as np' 
stmt1 = """\ 
my_data = np.genfromtxt('./test.csv', delimiter=',') 
""" 
stmt2 = """\ 
my_data = np.load('./testy.npy') 
""" 
stmt3 = """\ 
my_data = np.load('./testz.npz')['arr_0'] 
""" 

t1 = timeit.timeit(stmt=stmt1, setup=setup_stmt, number=3) 
t2 = timeit.timeit(stmt=stmt2, setup=setup_stmt, number=3) 
t3 = timeit.timeit(stmt=stmt3, setup=setup_stmt, number=3) 

genfromtxt 39.717250824 
save 0.0667860507965 
savez 0.268463134766 
+0

Dziękuję Ophion! To jest świetna odpowiedź i naprawdę przydatna - korzystam z cPickle, ale teraz zdałem sobie sprawę, że np.savez jest szybszy i bardziej kompaktowy niż cPickle, o ile używany jest tylko ndarray. Nie zaznaczyłem "zaakceptuj", ponieważ w tym pytaniu próbowałem odczytać dane z danych eksperymentalnych zapisanych przez LabVIEW. Ale wciąż, dziękuję bardzo! –

+0

Wierzę, że to powinno być wybrane jako poprawna odpowiedź! Dziękujemy @Ophion – Amir

0

Być może lepiej jest ustawić prosty kod c, który konwertuje dane na binarne i "numpy" odczytuje plik binarny. Mam plik CSV o pojemności 20 GB do odczytania z danymi CSV będącymi mieszaniną int, double, str. Numpy read-to-array struktur zajmuje więcej niż godzinę, podczas gdy zrzut do pliku binarnego trwa około 2 minuty, a ładowanie do numpy zajmuje mniej niż 2 sekundy!

Mój konkretny kod, na przykład, jest dostępny here.

+0

Dobre wyniki. Rozważ upuszczenie przykładowych kodów dla innych. –

+0

Zrobione, dziękuję za polecenie. – Arvind

0

FWIW wbudowany moduł CSV działa świetnie i naprawdę nie jest aż tak gadatliwy.

moduł csv:

%%timeit 
with open('test.csv', 'r') as f: 
    np.array([l for l in csv.reader(f)]) 


1 loop, best of 3: 1.62 s per loop 

np.loadtext:

%timeit np.loadtxt('test.csv', delimiter=',') 

1 loop, best of 3: 16.6 s per loop 

pd.read_csv:

%timeit pd.read_csv('test.csv', header=None).values 

1 loop, best of 3: 663 ms per loop 

Osobiście lubię pandy read_csv ale stosując moduł csv jest miło, gdy używam czystej numpy.

+0

Wiem, że to stare pytanie, ale jeśli nadal używasz czystej numpy, nadal możesz używać pand dla IO, a następnie użyć 'pd.DataFrame.values, aby wyodrębnić tablicę numpy. – Jakub