it-swarm.com.ru

Pandas read_csv low_memory и опции dtype

При звонке

df = pd.read_csv('somefile.csv')

Я получил:

/Users/josh/anaconda/envs/py27/lib/python2.7/site-packages/pandas/io/parsers.py:1130: DtypeWarning: столбцы (4,5,7,16) имеют смешанные типы. Укажите опцию dtype при импорте или установите low_memory = False.

Почему параметр dtype связан с low_memory и почему его настройка False может помочь в решении этой проблемы?

215
Josh

Устаревшая опция low_memory

Параметр low_memory не рекомендуется использовать должным образом, но так и должно быть, поскольку на самом деле он ничего не делает по-другому [ source ]

Причина, по которой вы получаете это low_memory предупреждение, заключается в том, что угадывание dtypes для каждого столбца требует очень много памяти. Pandas пытается определить тип dtype, анализируя данные в каждом столбце.

D-тип догадки (очень плохо)

Pandas может определить, какой тип d должен иметь столбец, только после того, как будет прочитан весь файл. Это означает, что на самом деле ничего не может быть проанализировано до того, как будет прочитан весь файл, если вы не рискуете изменить dtype этого столбца при чтении последнего значения.

Рассмотрим пример одного файла, в котором есть столбец с именем user_id. Он содержит 10 миллионов строк, где user_id - это всегда числа. Так как pandas не может знать, что это только числа, он, вероятно, будет сохранять его как исходные строки, пока не прочитает весь файл.

Указание dtypes (всегда должно быть сделано)

добавление

dtype={'user_id': int}

вызов pd.read_csv() заставит pandas узнать, когда он начнет читать файл, что это только целые числа.

Также стоит отметить, что если в последней строке файла будет записан "foobar" в столбце user_id, загрузка будет завершена, если указан вышеупомянутый dtype.

Пример сломанных данных, которые ломаются, когда определены dtypes

import pandas as pd
try:
    from StringIO import StringIO
except ImportError:
    from io import StringIO


csvdata = """user_id,username
1,Alice
3,Bob
foobar,Caesar"""
sio = StringIO(csvdata)
pd.read_csv(sio, dtype={"user_id": int, "username": object})

ValueError: invalid literal for long() with base 10: 'foobar'

типы dtypes, как правило, просто клочковатые, подробнее о них можно прочитать здесь: http://docs.scipy.org/doc/numpy/reference/generated/numpy.dtype.html

Какие типы существуют?

Это ntypty dtypes, которые также принимаются в пандах

[numpy.generic,
 [[numpy.number,
   [[numpy.integer,
     [[numpy.signedinteger,
       [numpy.int8,
        numpy.int16,
        numpy.int32,
        numpy.int64,
        numpy.int64,
        numpy.timedelta64]],
      [numpy.unsignedinteger,
       [numpy.uint8,
        numpy.uint16,
        numpy.uint32,
        numpy.uint64,
        numpy.uint64]]]],
    [numpy.inexact,
     [[numpy.floating,
       [numpy.float16, numpy.float32, numpy.float64, numpy.float128]],
      [numpy.complexfloating,
       [numpy.complex64, numpy.complex128, numpy.complex256]]]]]],
  [numpy.flexible,
   [[numpy.character, [numpy.bytes_, numpy.str_]],
    [numpy.void, [numpy.record]]]],
  numpy.bool_,
  numpy.datetime64,
  numpy.object_]]

Pandas также добавляет два dtypes: categorical и datetime64[ns, tz], которые недоступны в numpy

Пандас dtype ссылка

Gotchas, предостережения, заметки

Установка dtype=object заставит замолчать вышеупомянутое предупреждение, но не сделает его более эффективным с точки зрения памяти, а эффективнее всего процесса.

Установка dtype=unicode ничего не даст, так как, к сведению, unicode представляется как object.

Использование конвертеров

@sparrow правильно указывает на использование конвертеров во избежание взрыва pandas при обнаружении 'foobar' в столбце, указанном как int. Я хотел бы добавить, что конвертеры действительно тяжелые и неэффективные для использования в pandas и должны использоваться в качестве крайней меры. Это потому, что процесс read_csv является отдельным процессом.

CSV-файлы могут обрабатываться построчно и, следовательно, могут обрабатываться несколькими конвертерами параллельно более эффективно, просто разрезая файл на сегменты и выполняя несколько процессов, что pandas не поддерживает. Но это другая история.

303
firelynx

Пытаться:

dashboard_df = pd.read_csv(p_file, sep=',', error_bad_lines=False, index_col=False, dtype='unicode')

Согласно документации pandas:

dtype: введите имя или имя столбца -> тип

Что касается low_memory, это True по умолчанию и еще не задокументировано. Я не думаю, что это актуально, хотя. Сообщение об ошибке носит общий характер, так что вам все равно не нужно связываться с low_memory. Надеюсь, что это поможет, и дайте мне знать, если у вас есть дальнейшие проблемы

34
hd1
df = pd.read_csv('somefile.csv', low_memory=False)

Это должно решить проблему. Я получил точно такую ​​же ошибку при чтении 1,8M строк из CSV.

28
Neal

Как упоминалось ранее firelynx, если dtype явно указан, и есть смешанные данные, которые не совместимы с этим dtype, тогда загрузка завершится сбоем. Я использовал конвертер, подобный этому, в качестве обходного пути для изменения значений с несовместимым типом данных, чтобы данные все еще могли быть загружены.

def conv(val):
    if not val:
        return 0    
    try:
        return np.float64(val)
    except:        
        return np.float64(0)

df = pd.read_csv(csv_file,converters={'COL_A':conv,'COL_B':conv})
12
sparrow

У меня это работало с low_memory = False при импорте DataFrame. Вот и все изменения, которые сработали для меня:

df = pd.read_csv('export4_16.csv',low_memory=False)
1
Rajat Saxena

У меня была похожая проблема с файлом ~ 400 МБ. Установка low_memory=False сделала свое дело для меня. Сначала сделайте простые вещи, я бы проверил, что ваш фрейм данных не превышает системную память, перезагрузите компьютер, очистите RAM, прежде чем продолжить. Если вы по-прежнему сталкиваетесь с ошибками, стоит убедиться, что ваш файл .csv исправен, взгляните в Excel и убедитесь, что нет явных повреждений. Сломанные исходные данные могут нанести ущерб ...

0
Dr Nigel