Параметри 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 = Неправильно.

Чому цей dtypeваріант пов'язаний low_memoryі чому він Falseдопомагає вирішити цю проблему?


2
У мене є запитання щодо цього попередження. Чи вказується індекс стовпців на основі 0? Наприклад, стовпець 4 зі змішаним типом - це df [:, 4] або df [:, 3]
мазіар

@maziar під час читання CSV за замовчуванням створюється та використовується новий індекс на основі 0.
firelynx

Відповіді:


431

Застарений варіант low_memory

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

Причина, за якою ви це отримуєте low_memory попередження, полягає в тому, що відгадування типів для кожного стовпця дуже вимогливе до пам'яті. Pandas намагається визначити, який dtype встановити, аналізуючи дані в кожному стовпчику.

Гадання типу (дуже погано)

Панди можуть лише визначити, який тип файлу повинен мати типовий стовпчик після того, як буде прочитаний весь файл. Це означає, що нічого не можна реально розібрати перед тим, як прочитати весь файл, якщо ви не ризикуєте змінити тип цього стовпця під час читання останнього значення.

Розглянемо приклад одного файлу, який містить стовпець під назвою user_id. Він містить 10 мільйонів рядків, де user_id - це завжди цифри. Оскільки панди не можуть знати, що це лише числа, вони, ймовірно, зберігатимуть його як оригінальні рядки, поки не прочитають весь файл.

Визначення типів (завжди слід робити)

додавання

dtype={'user_id': int}

до pd.read_csv() виклику повідомляє панди, коли він почне читання файлу, що це лише цілі числа.

Також варто відзначити, що якби останній рядок у файлі був би "foobar"записаний у user_idстовпчик, завантаження припиниться, якби вказано вищевказаний тип.

Приклад розбитих даних, які розбиваються при визначенні 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'

типи, як правило, нумеровані речі, детальніше про них читайте тут: http://docs.scipy.org/doc/numpy/reference/generated/numpy.dtype.html

Які типи існують?

У нас є доступ до numpy-типів: float, int, bool, timedelta64 [ns] і datetime64 [ns]. Зауважте, що нумеровані дати / часові типи не відомі часовому поясу.

Pandas розширює цей набір типів власних:

'datetime64 [ns,]' Що є часовою позначкою часового поясу.

'категорія', яка по суті є перерахуванням (рядки, представлені цілими ключами для збереження

'period []' Не плутати з тиммеделтою, ці об'єкти фактично прив’язані до певних часових періодів

'Sparse', 'Sparse [int]', 'Sparse [float]' призначений для розріджених даних або 'Data, у яких багато дірок' Замість збереження NaN або None у фреймі даних він опускає об'єкти, економлячи місце .

"Інтервал" є власною темою, але його основне використання використовується для індексування. Детальніше дивіться тут

'Int8', 'Int16', 'Int32', 'Int64', 'UInt8', 'UInt16', 'UInt32', 'UInt64' - це цілі цілі цілі числа панд, які є нульовими, на відміну від numpy-варіанту.

'string' - це специфічний тип роботи для даних із рядковими даними та надає доступ до .strатрибуту серії.

'boolean' - це як numpy 'bool', але він також підтримує відсутні дані.

Прочитайте повну посилання тут:

Посилання на тип панди

Готчі, застереження, замітки

Налаштування dtype=objectзамовчуватиме вищезазначене попередження, але не зробить його більш ефективним у пам’яті.

Налаштування dtype=unicodeнічого не зробить, оскільки для нумерування, a unicodeпозначається як object.

Використання перетворювачів

@sparrow правильно вказує на використання перетворювачів, щоб уникнути вибуху панд при зустрічі 'foobar'в стовпці, вказаному якint . Я хотів би додати, що перетворювачі дійсно важкі та неефективні для використання в пандах, і їх слід використовувати в крайньому випадку. Це тому, що процес read_csv - це єдиний процес.

CSV-файли можна обробляти по черзі, і таким чином вони можуть оброблятись декількома перетворювачами паралельно ефективніше, просто розрізаючи файл на сегменти та виконуючи кілька процесів, що панда не підтримує. Але це вже інша історія.


6
Отже, враховуючи, що настройка a dtype=objectне є більш ефективною пам’яттю, чи є причина, щоби повозитися з нею, крім позбавлення від помилки?
zthomas.nc

6
@ zthomas.nc так, Pandas не потребує турбуватися про те, що знаходиться у стовпці. Теоретично збереження деякої пам’яті під час завантаження (але жодна після завершення завантаження) і теоретично збереження деяких циклів процесора (яких ви не помітите, оскільки
вузол

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

5
@sparrow може бути, але останній раз, коли я його використовував, у ньому були помилки. Це може бути зафіксовано в останній версії панди. error_bad_lines=False, warn_bad_lines=Trueповинен зробити трюк. У документації сказано, що вона діє лише з аналізатором C. Він також говорить, що аналізатор за замовчуванням є None, що важко зрозуміти, який з них є типовим.
firelynx

5
@nealmcb Ви можете прочитати фрейм даних nrows=100як аргумент, а потім зробити, df.dtypesщоб побачити отримані типи. Однак, читаючи весь фрейм даних з цими типами, не забудьте зробити це, try/exceptщоб ви знайшли несправні здогадки про тип. Дані брудні ви знаєте.
firelynx

50

Спробуйте:

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

Відповідно до документації на панди:

dtype: Введіть назву або дікта колонки -> type

Що стосується low_memory, то це за замовчуванням True та ще не задокументовано. Я не думаю, що це доречно. Повідомлення про помилку є загальним, тому вам не потрібно буде возитися з low_memory так чи інакше. Сподіваюся, це допоможе, і повідомте мене, якщо у вас виникнуть подальші проблеми


1
Додавання dtype=unicodeвиробництва: NameError: name 'unicode' is not defined. Але введення unicodeлапок (як у 'unicode'), здається, працює!
sedeh

5
@sedeh Ви можете вказати dtypes або як тип python або як numpy.dtype('unicode'). Коли ви надаєте опції dtype рядок, вона спробує передати її numpy.dtype()за замовчуванням. Вказання 'unicode'насправді нічого не зробить, унікоди просто змінені objects. Ви отримаєтеdtype='object'
firelynx

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

Це має вирішити питання. Я отримав абсолютно таку ж помилку, коли читав 1,8М рядків з 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. Використовуючи вищевикладене, я все-таки зіткнувся з проблемою, пов’язаною з файлом_формату, який не міг бути визначено на основі імені файлу (виправлено за допомогою спробу .. крім ..)

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)
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.