Панды read_csv low_memory и опции dtype

320

При звонке

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поможет решить эту проблему?

мистифицировать
источник
2
У меня есть вопрос об этом предупреждении. Индекс столбцов, упомянутых 0, основан на 0? Например, столбец 4, который имеет смешанный тип, это то, что df [:, 4] или df [:, 3]
мазиар
@maziar при чтении csv, по умолчанию создается и используется новый индекс на основе 0.
firelynx

Ответы:

433

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

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

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

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

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

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

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

добавление

dtype={'user_id': int}

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

Также стоит отметить, что если бы последняя строка в файле была "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": "string"})

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

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

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

У нас есть доступ к numpy dtypes: float, int, bool, timedelta64 [ns] и datetime64 [ns]. Обратите внимание на то, что ntypty dtypes даты / времени не осведомлены о часовом поясе.

Панды расширяет этот набор dtypes своим собственным:

datetime64 [ns,], которая является временной меткой с учетом часового пояса.

'category', которая по сути является enum (строки, представленные целочисленными ключами для сохранения

'period []' Не путать с timedelta, эти объекты фактически привязаны к определенным периодам времени

«Sparse», «Sparse [int]», «Sparse [float]» предназначены для разреженных данных или «данных, в которых много дырок». Вместо сохранения NaN или None в кадре данных он пропускает объекты, экономя место ,

«Интервал» - это отдельная тема, но его основное использование - индексация. Подробнее здесь

«Int8», «Int16», «Int32», «Int64», «UInt8», «UInt16», «UInt32», «UInt64» - это все целые числа для панд, которые могут иметь значение null, в отличие от простого варианта.

'string' - это определенный тип d для работы со строковыми данными, который предоставляет доступ к .strатрибуту в серии.

'boolean' похож на numy 'bool', но он также поддерживает отсутствующие данные.

Прочитайте полную ссылку здесь:

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

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

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

Установка dtype=unicodeне будет делать ничего, так как для numpy, a unicodeпредставляется как object.

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

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

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

firelynx
источник
6
Итак, учитывая, что установка a dtype=objectне более эффективна для использования памяти, есть ли причина возиться с ней, кроме как избавиться от ошибки?
zthomas.nc
6
@ zthomas.nc да, Пандам не нужно беспокоиться о том, что находится в столбце. Теоретически экономия некоторой памяти во время загрузки (но ни одной после завершения загрузки) и теоретическое сохранение некоторых циклов ЦП (что вы не заметите, поскольку дисковый ввод-вывод будет узким местом)
firelynx
5
«Также стоит отметить, что если в последней строке файла будет записан« foobar »в столбце user_id, загрузка завершится сбоем, если указан вышеупомянутый тип dtype». Есть ли какая-нибудь "принудительная" опция, которую можно использовать, чтобы выбросить этот ряд вместо сбоя?
Воробей
5
@ Воробей может быть, но в прошлый раз, когда я использовал его, у него были ошибки. Это может быть исправлено в последней версии панд. error_bad_lines=False, warn_bad_lines=Trueдолжен сделать свое дело. Документация говорит, что это допустимо только с синтаксическим анализатором C. В нем также говорится, что парсером по умолчанию является None, что затрудняет определение того, какой парсер используется по умолчанию.
firelynx
5
@nealmcb Вы можете прочитать фрейм данных nrows=100в качестве аргумента, а затем сделать, df.dtypesчтобы увидеть dtypes, которые вы получаете. Однако при чтении всего кадра данных с этими dtypes обязательно сделайте try/exceptтак, чтобы вы уловили ошибочные догадки dtype. Вы знаете, что данные грязные.
firelynx
50

Пытаться:

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

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

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

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

hd1
источник
1
Добавление dtype=unicodeпроизводства: NameError: name 'unicode' is not defined. Но вставка unicodeв кавычки (как в 'Unicode'), кажется, работает!
Седе
5
@sedeh Вы можете указать dtypes либо как типы python, либо как numpy.dtype('unicode'). Когда вы даете опции dtype строку, она будет пытаться привести ее через numpy.dtype()фабрику по умолчанию. Указание на 'unicode'самом деле ничего не даст, юникоды просто преобразуются objects. Вы получитеdtype='object'
firelynx
44
df = pd.read_csv('somefile.csv', low_memory=False)

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

Нил
источник
51
Это заглушает ошибку, но на самом деле ничего не меняет.
firelynx
2
У меня та же проблема при запуске 1,5 ГБ файла данных
Sitz Blogz
18

Как упоминалось ранее 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})
воробей
источник
2

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

Доктор Найджел
источник
1

Я столкнулся с аналогичной проблемой при обработке огромного CSV-файла (6 миллионов строк). У меня было три проблемы: 1. файл содержал странные символы (исправлено с помощью кодировки) 2. тип данных не был указан (исправлено с помощью свойства dtype) 3. При использовании вышеупомянутого я все еще сталкивался с проблемой, связанной с file_format, которая не могла быть определяется на основе имени файла (исправлено с помощью try .. кроме ..)

df = pd.read_csv(csv_file,sep=';', encoding = 'ISO-8859-1',
                 names=['permission','owner_name','group_name','size','ctime','mtime','atime','filename','full_filename'],
                 dtype={'permission':str,'owner_name':str,'group_name':str,'size':str,'ctime':object,'mtime':object,'atime':object,'filename':str,'full_filename':str,'first_date':object,'last_date':object})

try:
    df['file_format'] = [Path(f).suffix[1:] for f in df.filename.tolist()]
except:
    df['file_format'] = ''
Вим Фолкертс
источник
-1

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

df = pd.read_csv('export4_16.csv',low_memory=False)
Раджат Саксена
источник