Подтвердить что ты не робот

Загрузка Numy csv TOO медленнее по сравнению с Matlab

Я разместил этот вопрос, потому что мне было интересно, сделал ли я что-то ужасное, чтобы получить этот результат.

У меня есть файл csv среднего размера, и я попытался использовать numpy для его загрузки. Для иллюстрации я сделал файл с помощью python:

import timeit
import numpy as np

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

И затем я попробовал два метода: 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)

И результат показывает, что t1 = 32.159652940464184, t2 = 52.00093725634724.
Однако, когда я попытался использовать matlab:

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

Результат показывает: Истекшее время 3.196465 секунд.

Я понимаю, что могут быть некоторые различия в скорости загрузки, но:

  • Это намного больше, чем я ожидал;
  • Не правда ли, что np.loadtxt должен быть быстрее, чем np.genfromtxt?
  • Я еще не пробовал модуль csv python, потому что загрузка csv файла - это очень частое, что я делаю, и с модулем csv, кодирование немного подробное... Но я был бы рад попробовать, если это единственный путь. В настоящее время меня больше беспокоит, что я делаю что-то неправильно.

Любой ввод будет оценен. Большое спасибо заранее!

4b9b3361

Ответ 1

Да, чтение csv файлов в numpy довольно медленно. Там есть много чистого Python по коду. В эти дни, даже когда я использую чистый numpy, я все еще использую pandas для 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

В качестве альтернативы, в достаточно простом случае, таком как этот, вы можете использовать что-то вроде того, что Джо Кингтон написал здесь:

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

Там также используется Warren Weckesser textreader, в случае, если pandas слишком тяжелая зависимость:

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

Ответ 2

Если вы хотите просто сохранить и прочитать массив numpy, гораздо лучше сохранить его как двоичный или сжатый двоичный файл в зависимости от размера:

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

Ответ 3

Возможно, лучше подстроить простой c-код, который преобразует данные в двоичный файл и "numpy" читает двоичный файл. У меня есть файл CSV на 20 ГБ для чтения с данными CSV, представляющими собой смесь int, double, str. Numpy read-to-array structs занимает больше часа, в то время как сбрасывание в двоичный файл занимает около 2 минут, а загрузка до numpy занимает менее 2 секунд!

Мой конкретный код, например, доступен здесь.

Ответ 4

FWIW встроенный модуль csv отлично работает и на самом деле не является подробным.

Модуль 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

Лично мне нравится использовать pandas read_csv, но модуль csv хорош, когда я использую чистый numpy.