pandas.read_csv()
:import pandas df = pandas.read_csv(filepath_or_buffer, *, sep=',', delimiter=None, header='infer', names=None, index_col=None, usecols=None, dtype=None, engine=None, converters=None, true_values=None, false_values=None, skipinitialspace=False, skiprows=None, skipfooter=0, nrows=None, na_values=None, keep_default_na=True, na_filter=True, verbose=False, skip_blank_lines=True, parse_dates=None, infer_datetime_format=False, keep_date_col=False, date_parser=no_default, date_format=None, dayfirst=False, cache_dates=True, iterator=False, chunksize=None, compression='infer', thousands=None, decimal='.', lineterminator=None, quotechar='"', quoting=0, doublequote=True, escapechar=None, comment=None, encoding=None, encoding_errors='strict', dialect=None, on_bad_lines='error', delim_whitespace=False, low_memory=True, memory_map=False, float_precision=None, storage_options=None, dtype_backend='numpy_nullable')
pandas.read_csv()
:filepath_or_buffer
- любой допустимый путь в виде строки. Строка может быть URL. Допустимые схемы URL включают http(s)
, ftp(s)
, s3
, gs
и file
. Для URL-адресов файлов ожидается host
. Локальным файлом может быть: file://localhost/path/to/table.csv
.
Если необходимо передать объект pathlib
, то этот аргумент принимает любой оs.PathLike
.
Аргумент также поддерживает объекты подобные открытому файлу, у которых есть метод file.read()
, такие как дескриптор файла (например, открытый файл open()
) или io.StringIO
.
sep=‘,’
- Символ или шаблон регулярного выражения для использования в качестве разделителя. Если sep=None
, то C-движок не может автоматически определить разделитель, но движок синтаксического анализа Python может. Это означает, что будет использоваться последний и автоматически обнаружит разделитель только из первой допустимой строки файла встроенным инструментом сниффера Python, csv.Sniffer
. Кроме того, разделители длиной более 1 символа и отличные от '\s+'
будут интерпретироваться как регулярные выражения, а также принудительно использовать механизм синтаксического анализа Python. Обратите внимание, что разделители регулярных выражений склонны игнорировать данные, заключенные в кавычки. Пример регулярного выражения: '\r\t'
.
delimiter=None
- псевдоним для аргумента sep
.
header='infer'
- номер(a) строки(строк), содержащие метки столбцов и отмечают начало данных (с нулевым индексом). Поведение по умолчанию заключается в выводе имен столбцов: если аргумент names
не передается, то поведение идентично header=0
, а имена столбцов выводятся из первой строки файла, если имена столбцов передаются явно в names
, то поведение идентично header=None
. Чтобы иметь возможность заменять существующие имена, нужно явно передать header=0
. Аргумент header
может представлять собой список целых чисел, которые определяют расположение строк для MultiIndex
в столбцах, например [0, 1, 3]
. Промежуточные строки, которые не указаны, будут пропущены (например, строка 2 в этом примере пропущена). Обратите внимание, что этот аргумент игнорирует пустые и закомментированные строки, если skip_blank_lines=True
, поэтому header=0
обозначает первую строку данных, а не первую строку файла.
names=None
- список меток столбцов (список имен столбцов). Если файл содержит строку заголовка, то следует явно передать header=0
, чтобы переопределить имена столбцов. Дубликаты в этом списке не допускаются.
index_col=None
- столбцы для использования в качестве меток строк DataFrame
, заданные как имя или индекс столбца. Если передан список int
/str
, то будет создан MultiIndex
.
Примечание.
index_col=False
можно использовать, чтобы не использовать первый столбец в качестве индекса, например. когда есть некорректный файл с разделителями в конце каждой строки.
Значение по умолчанию None
определяет следующее поведение. Если количество полей в строке заголовка столбца равно количеству полей в теле файла данных, то используется индекс по умолчанию. Если он больше, то первые столбцы используются в качестве индекса, так что оставшееся количество полей в теле равно количеству полей в заголовке.
Первая строка после заголовка используется для определения количества столбцов, которые войдут в индекс. Если последующие строки содержат меньше столбцов, чем первая строка, то они заполняются значением NaN
.
Этого можно избежать с помощью аргумента usecols
. Он гарантирует, что столбцы принимаются как есть, а конечные данные игнорируются.
usecols=None
- подмножество выбираемых столбцов, обозначаемых либо метками столбцов, либо индексами столбцов. Если это список, то все элементы должны быть либо позиционными (т. е. целочисленными индексами в столбцах с данными), либо строками, которые соответствуют именам столбцов, предоставленным либо пользователем в names
, либо полученным из строк заголовка документа. Если указаны имена, то строки заголовка документа не принимаются во внимание. Например допустимым, что usecols
, это список [0, 1, 2] или ['foo', 'bar', 'baz']. Порядок элементов игнорируется, поэтому usecols=[0, 1]
совпадает с [1, 0]
. Чтобы создать экземпляр DataFrame
с сохранением порядка элементов ['foo', 'bar']
, нужно использовать вызов pd.read_csv(data, usecols=['foo', 'bar'])[['foo', 'bar']]
или pd.read_csv(data, usecols=['foo', 'bar'])[['bar', 'foo']]
для порядка столбцов ['bar', 'foo']
.
Если значением аргумента является вызываемая функция, то она будет вычисляться по именам столбцов, возвращая имена, в которых вызываемая функция принимает значение True
:
>>> import pandas as pd >>> from io import StringIO >>> data = "col1,col2,col3\na,b,1\na,b,2\nc,d,3" >>> pd.read_csv(StringIO(data)) # col1 col2 col3 # 0 a b 1 # 1 a b 2 # 2 c d 3 >>> pd.read_csv(StringIO(data), usecols=lambda x: x.upper() in ["COL1", "COL3"]) # col1 col3 # 0 a 1 # 1 a 2 # 2 c 3
Использование этого аргумента приводит к гораздо более быстрому анализу и меньшему использованию памяти. Механизм Python сначала загружает данные, прежде чем решить, какие столбцы следует удалить.
dtype=None
- тип данных, который применяется ко всему набору данных, либо в случае передачи словаря с типами данных - к отдельным столбцам. Например, {'a': np.float64, 'b': np.int32, 'c': 'Int64'}
. Чтобы сохранить, а не интерпретировать dtype
необходимо использовать типы str
или object
вместе с подходящими настройками na_values
. Если указаны конвертеры converters
, то они будут применены ВМЕСТО преобразования dtype
.
engine=None
- используемый парсер, принимает значения: 'c'
, 'pyarrow'
, 'python'
. Движки C и Pyarrow работают быстрее, а движок Python в настоящее время более функционален. Многопоточность в настоящее время поддерживается только движком Pyarrow.
converters=None
- словарь функции для преобразования значений в указанных столбцах (ключах). Ключами могут быть либо метки столбцов, либо индексы столбцов.
true_values=None
- список строк, которые следует рассматривать как True
в дополнение к варианту 'True'
без учета регистра. Например, ['y', 'yes', 'ok']
false_values=None
- список строк, которые следует рассматривать как False
в дополнение к варианту 'False'
без учета регистра. Например, ['n', 'no']
skipinitialspace=False
- пропускать пробелы после разделителя или нет.
skiprows=None
- список номеров строк для пропуска (с индексом 0) или количество строк для пропуска (int
) в начале файла.
Если это вызываемая функция, то она будет оцениваться по индексам строк, возвращая True
, если строка должна быть пропущена, и False
в противном случае.
>>> data = "col1,col2,col3\na,b,1\na,b,2\nc,d,3" >>> pd.read_csv(StringIO(data)) # col1 col2 col3 # 0 a b 1 # 1 a b 2 # 2 c d 3 >>> pd.read_csv(StringIO(data), skiprows=lambda x: x % 2 != 0) col1 col2 col3 # 0 a b 2
skipfooter=0
- количество строк в нижней части файла, которые нужно пропустить (не поддерживается, если аргумент engine='c'
).
nrows=None
- количество строк файла для чтения. Полезно для чтения фрагментов больших файлов.
na_values=None
- список строк для распознавания значений NA
/NaN
. Если передан словарь, то в нем указываются конкретные значения NA
для каждого столбца (ключи). По умолчанию следующие значения интерпретируются как NaN
: ' '
, '#N/A'
, '#N/A N/A”
, '#NA'
, '-1.#IND'
, '-1.#QNAN'
, '-NaN'
, '-nan'
, '1.#IND'
, '1.#QNAN'
, '<NA>'
, 'N/A'
, 'NA'
, 'NULL'
, 'NaN'
, 'None'
, 'n/a'
, 'nan'
, 'null'
.
keep_default_na=True
- включать или не включать значения NaN
по умолчанию при анализе данных. В зависимости от того, передается ли параметр na_values
, поведение будет следующим:
keep_default_na=True
и указано na_values
, то na_values
добавляется к значениям NaN
по умолчанию.keep_default_na=True
, а na_values
не указаны, то для синтаксического анализа используются только значения NaN
по умолчанию.keep_default_na=False
и указано na_values
, то для синтаксического анализа используются только значения NaN
, указанные в na_values
.keep_default_na=False
, а na_values
не указаны, то никакие строки не будут проанализированы как NaN
.Обратите внимание, что если na_filter
передается как False
, то аргументы keep_default_na
и na_values
будут проигнорированы.
na_filter=True
- обнаружение маркеров отсутствующих значений (пустые строки и значения na_values
). В данных, без каких-либо значений NA
передача na_filter=False
может повысить производительность чтения большого файла.
verbose=False
- есть ли значений NA
в нечисловых столбцах.
skip_blank_lines=True
- значение True
, пропускает пустые строки, а не интерпретирует их как значения NaN
.
parse_dates=None
- принимает bool
, список, список списков или словарь списков.
Поведение заключается в следующем:
True
- попробует проанализировать индекс. Примечание: автоматически устанавливается в True
, если были переданы аргументы date_format
или date_parser
.[1, 2, 3]
- попробует разобрать столбцы 1, 2, 3 каждый как отдельный столбец даты.[[1, 3]]
- объединит столбцы 1 и 3 и проанализировать как один столбец даты. (Устарело с версии pandas
2.2, объедините нужные столбцы с pandas.to_datetime()
после синтаксического анализа).{'foo' : [1, 3]}
- разбирает столбцы 1, 3 как дату и вызывает результат ‘foo’. Значения объединяются пробелом перед разбором.Если столбец или индекс не могут быть представлены в виде массива datetime
, скажем, из-за неразличимого значения или сочетания часовых поясов, то столбец или индекс будут возвращены без изменений как объектный тип данных. Для нестандартного анализа даты/времени, после прочтения данных в DataFrame
, необходимо использовать pandas.to_datetime()
.
Примечание. Для дат в формате
iso8601
существует быстрый путь.
infer_datetime_format=False
- (Устарело с версии pandas
2.0, строгая версия этого аргумента теперь используется по умолчанию) если True
и включен parse_dates
, то pandas
попытается определить формат строк даты и времени в столбцах, и если это возможно, переключится на более быстрый метод анализа. В некоторых случаях это может увеличить скорость парсинга в 5-10 раз.
keep_date_col=False
- если True
и parse_dates
указывает объединение нескольких столбцов (устарело с версии pandas
2.2 и будет удалено в будущей версии), то сохраняет исходные столбцы.
date_parser=no_default
- (Устарело с версии pandas
2.0, используйте pandas.to_datetime()
после синтаксического анализа) функция, используемая для преобразования последовательности строковых столбцов в массив экземпляров даты/времени. По умолчанию для преобразования используется dateutil.parser.parser
. Pandas попытается вызвать date_parser
тремя разными способами, переходя к следующему в случае возникновения исключения:
parse_dates
); parse_dates
, в один массив и передать его; date_parser
один раз для каждой строки, используя в качестве аргументов одну или несколько строк (соответствующих столбцам, определенным в parse_dates
).date_format=None
- строка формата (например, '%d/%m/%Y'
), используемая для анализа даты совместно с parse_dates
. Информацию о вариантах строки формата смотрите в документации по strftime
, но учтите, что '%f'
будет анализировать вплоть до наносекунд. Также вы можно передать:
'ISO8601'
, для анализа любого ISO8601. Cтрока времени (не обязательно в том же формате);'mixed'
- определяет формат для каждого элемента индивидуально. Это рискованно, следует использовать его вместе с аргументом dayfirst
.dayfirst=False
- используемый формат - международный (False
- первый идет год) и европейский (True
- первый идет день) формат.
cache_dates=True
- если True
, то используйте кэш уникальных преобразованных дат. Может значительно ускорить анализ повторяющихся строк даты, особенно со смещением часового пояса.
iterator=False
- возвращает объект TextFileReader
для итерации или получения фрагментов с помощью get_chunk()
.
chunksize=None
- количество строк для чтения фрагмента из файла. Передача значения приведет к тому, что функция вернет объект TextFileReader
для итерации.
compression='infer'
- если имеет значение 'infer'
, а аргумент filepath_or_buffer
является объектом оs.PathLike
(например модуль pathlib
), то самостоятельно обнаружит сжатие из следующих расширений: '.gz'
, '.bz2'
, '.zip'
, '.xz'
, '.zst'
, '.tar'
, '.tar.gz'
, '.tar.xz'
или '.tar.bz2'
(в противном случае сжатие отсутствует).
При передачи значения ‘zip’
или ‘tar’
ZIP-файл должен содержать только один файл данных для чтения. Значение None
говорит об отсутствии сжатия.
thousands=None
- один символ, действующий как разделитель тысяч в числовых значениях .
decimal='.'
- один символ, который нужно распознать как десятичную точку.
lineterminator=None
- символ, используемый для обозначения разрыва строки. Действует только с аргументом engine='c'
.
quotechar='"'
- один символ, используемый для обозначения начала и конца элемента, заключенного в кавычки. Элементы, заключенные в кавычки, могут содержать разделитель, который определен аргументом delimiter
, и он будет проигнорирован.
quoting=0
- управляет поведением при цитировании полей в формате csv.QUOTE_*
. По умолчанию используется формат csv.QUOTE_MINIMAL
(т.е. 0), это подразумевает, что в кавычки заключаются только поля, содержащие специальные символы (например, символы, определенные в аргументах quotechar
, delimiter
или lineterminator
. Принимает значения 0
или csv.QUOTE_MINIMAL
, 1 или csv.QUOTE_ALL
, 2 или csv.QUOTE_NONNUMERIC
, 3 или csv.QUOTE_NONE
.
doublequote=True
- если указан аргумент quotechar
, а значение quoting
не равно csv.QUOTE_NONE
, указывает, следует ли интерпретировать два последовательных элемента quotechar
ВНУТРИ поля как один элемент quotechar
.
escapechar=None
- символ, используемый для экранирования других символов.
comment=None
- символ, указывающий, что остаток строки не следует анализировать. Если он находится в начале строки, то строка будет полностью проигнорирована. Этот аргумент должен состоять из одного символа. Как и пустые строки (при условии, что skip_blank_lines=True
), полностью закомментированные строки игнорируются header
, но не skiprows
. Например, если comment='#'
, то синтаксический анализ строки #empty\na,b,c\n1,2,3
с header=0 приведет к тому, что 'a,b,c' будет рассматриваться как заголовок.
encoding=None
- используемая кодировка при чтении/записи (например, 'utf-8'
)
encoding_errors='strict'
- как обрабатывать ошибки кодирования. Список возможных значений.
dialect=None
- если указан, то переопределяет значения для следующих аргументов: delimiter
, doublequote
, escapechar
, skipinitialspace
, quotechar
и quoting
. Для получения более подробной информации, смотрите csv.Dialect
.
on_bad_lines='error'
- указывает, что делать при обнаружении некорректной строки (строки со слишком большим количеством полей).
Допустимые значения:
'error'
, вызывает исключение при обнаружении некорректной строки.'warn'
, выводит предупреждение при обнаружении неправильной строки и пропускает эту строку.'skip'
, молча пропускает неправильные строки.delim_whitespace=False
- (Устарело с версии pandas
2.2, используйте sep='\s+'
) указывает, будет ли в качестве разделителя sep
использоваться пробел (например, ''
или \t
) . Если эта опция установлена на True
, то ничего не должно быть передано для аргумента sep
.
low_memory=True
- внутренняя обработка файла по частям, что приводит к меньшему использованию памяти при синтаксическом анализе, но, возможно, к выводу смешанного типа. Чтобы гарантировать отсутствие смешанных типов, нужно установить значение False
, либо указать тип в аргументе dtype
. Обратите внимание, что независимо от того, что весь файл считывается в один фрейм данных, использует аргументы chunksize
или iterator
, для возврата данных порциями. (Допустимо только с аргументом engine='c'
).
memory_map=False
- если для аргумента filepath_or_buffer
указан путь к файлу, то сопоставляет файловый объект непосредственно с памятью и получает доступ к данным непосредственно оттуда. Использование этого аргумента может повысить производительность.
float_precision=None
- указывает, какой механизм C должен использовать для преобразования значений с float
. Возможные варианты: None
или 'high'
для обычного конвертера, 'legacy'
для исходного конвертера pandas
с более низкой точностью и 'round_trip'
для двустороннего конвертера.
storage_options=None
- дополнительные параметры, которые имеют смысл для конкретного подключения к хранилищу. Например, хост, порт, имя пользователя, пароль и т. д. Для URL-адресов HTTP(S) пары ключ-значение пересылаются в urllib.request.Request
в качестве заголовков.
dtype_backend='numpy_nullable'
- (экспериментальный) внутренний тип данных, применяемый к результирующему DataFrame
.
Поведение выглядит следующим образом:
'numpy_nullable'
: возвращает фрейм с поддержкой null-dtype
(по умолчанию).'pyarrow'
: возвращает фрейм данных ArrowDtype
с нулевым значением, поддерживаемый pyarrow
.pandas.read_csv()
:DataFrame
или TextFileReader
в виде двумерной структуры данных с помеченными осями.pandas.read_csv()
Функция read_csv()
модуля pandas
читает файл с данными, разделенных запятыми (CSV), в DataFrame
. Поддерживает опциональную итерацию или разбиение файла на куски.
Для чтения удаленных файлов можно передавать URL-адрес во многие функции ввода-вывода pandas
. В следующем примере показано чтение CSV-файла по HTTPS
протоколу:
pd.read_csv("https://download.bls.gov/pub/time.series/cu/cu.item", sep="\t")
Пользовательский заголовок можно отправить вместе с запросами HTTP(s), передав словарь сопоставлений значений ключа заголовка в ключевой аргумент storage_options
, как показано ниже:
headers = {"User-Agent": "pandas"} df = pd.read_csv( "https://download.bls.gov/pub/time.series/cu/cu.item", sep="\t", storage_options=headers )
Функция read_csv()
способен выводить файлы с разделителями (не обязательно разделенными запятыми), т.к. pandas
использует класс csv.Sniffer
модуля csv
. Для этого необходимо указать sep=None
.
>>> df = pd.DataFrame(np.random.randn(10, 4)) >>> df.to_csv("tmp2.csv", sep=":", index=False) >>> pd.read_csv("tmp2.csv", sep=None, engine="python") # 0 1 2 3 # 0 -3.090337 -1.071775 0.094097 -0.193111 # 1 1.656500 -1.887067 -0.473435 0.164553 # 2 0.141371 0.343371 -0.382775 -1.184313 # 3 -0.856343 0.064099 -0.437490 -2.243752 # 4 -0.766447 -0.323522 1.168509 0.815811 # 5 0.442197 0.162073 -0.641610 -0.498648 # 6 0.506010 -1.483942 -0.659766 0.019671 # 7 -0.130446 -0.664035 -0.731641 -0.917420 # 8 -1.273134 1.280339 -0.864498 0.165605 # 9 0.396454 0.942713 -2.208943 1.915031
dtype
)При чтении данных можно сразу указать тип данных для всего DataFrame
или отдельных столбцов:
>>> import numpy as np >>> import pandas as pd >>> from io import StringIO >>> data = "a,b,c,d\n1,2,3,4\n5,6,7,8\n9,10,11" >>> df = pd.read_csv(StringIO(data), dtype=object) >>> df # a b c d # 0 1 2 3 4 # 1 5 6 7 8 # 2 9 10 11 NaN >>> df["a"][0] # '1' # указываем желаемые типы для столбцов >>> df = pd.read_csv(StringIO(data), dtype={"b": object, "c": np.float64, "d": "Int64"}) >>> df.dtypes # a int64 # b object # c float64 # d Int64 # dtype: object
Например, можно использовать аргумент converters
функции read_csv()
:
>>> data = "col_1\n1\n2\n'A'\n4.22" >>> df = pd.read_csv(StringIO(data), converters={"col_1": str}) >>> df # col_1 # 0 1 # 1 2 # 2 'A' # 3 4.22 >>> df["col_1"].apply(type).value_counts() # col_1 # <class 'str'> 4 # Name: count, dtype: int64
Или можно использовать функцию pandas.to_numeric()
для принудительного преобразования типов после чтения данных:
>>> df2 = pd.read_csv(StringIO(data)) >>> df2["col_1"] = pd.to_numeric(df2["col_1"], errors="coerce") >>> df2 # col_1 # 0 1.00 # 1 2.00 # 2 NaN # 3 4.22 >>> df2["col_1"].apply(type).value_counts() # col_1 # <class 'float'> 4 # Name: count, dtype: int64
В конечном счете, чтением столбцов, содержащих смешанные типы данных, зависит от конкретных потребностей. В приведенном выше случае, если необходимо выявить аномалии данных с помощью NaN
, то pandas.to_numeric()
, вероятно, будет лучшим вариантом. Но если нужно, чтобы все данные были преобразованы независимо от их типа, то стоит использовать аргумент converters
функции read_csv()
.
Примечание. В некоторых случаях чтение аномальных данных со столбцами, содержащими смешанные типы данных, приведет к несогласованному набору данных. Если возложить определение типов столбцов на
pandas
, то механизм синтаксического анализа будет выводить типы данных для разных фрагментов данных, а не для всего набора данных сразу. Следовательно, можно получить столбцы со смешанными типами данных. Например:
>>> col_1 = list(range(500000)) + ["a", "b"] + list(range(500000)) >>> df = pd.DataFrame({"col_1": col_1}) >>> df.to_csv("foo.csv") >>> mixed_df = pd.read_csv("foo.csv") >>> mixed_df["col_1"].apply(type).value_counts() # col_1 # <class 'int'> 737858 # <class 'str'> 262144 # Name: count, dtype: int64 >>> mixed_df["col_1"].dtype # dtype('O')
в результате mixed_df
будет содержаnm тип int
для определенных фрагментов столбца и str
для других из-за смешанных типов dtype
. Важно отметить, что весь столбец будет отмечен dtype: object
, который используется для столбцов со смешанными типами данных.
Установка аргумента dtype_backend='numpy_nullable'
приведет к созданию dtypes
, допускающих значение NULL
, для каждого столбца.
data = """a,b,c,d,e,f,g,h,i,j 1,2.5,True,a,,,,,12-31-2019, 3,4.5,False,b,6,7.5,True,a,12-31-2019, """ >>> df = pd.read_csv(StringIO(data), dtype_backend="numpy_nullable", parse_dates=["i"]) >>> df # a b c d e f g h i j # 0 1 2.5 True a <NA> <NA> <NA> <NA> 2019-12-31 <NA> # 1 3 4.5 False b 6 7.5 True a 2019-12-31 <NA> >>> df.dtypes # a Int64 # b Float64 # c boolean # d string[python] # e Int64 # f Float64 # g boolean # h string[python] # i datetime64[ns] # j Int64 # dtype: object
dtype
Столбцы Categorical
можно анализировать напрямую, указав аргумент dtype='category'
или dtype=CategoricalDtype(categories,ordered)
.
>>> data = "col1,col2,col3\na,b,1\na,b,2\nc,d,3" >>> pd.read_csv(StringIO(data)) # col1 col2 col3 # 0 a b 1 # 1 a b 2 # 2 c d 3 >>> pd.read_csv(StringIO(data)).dtypes # col1 object # col2 object # col3 int64 # dtype: object >>> pd.read_csv(StringIO(data), dtype="category").dtypes # col1 category # col2 category # col3 category # dtype: object
Используя словарь, можно анализировать отдельные столбцы как категориальные Categorical
:
>>> pd.read_csv(StringIO(data), dtype={"col1": "category"}).dtypes # col1 category # col2 object # col3 int64 # dtype: object
Указание dtype='category'
приведет к созданию неупорядоченного значения Categorical
, категории которого представляют собой уникальные значения, наблюдаемые в данных. Для бОльшего контроля над категориями и порядком нужно заранее создать CategoricalDtype
и передать его для dtype
этого столбца.
>>> from pandas.api.types import CategoricalDtype >>> dtype = CategoricalDtype(["d", "c", "b", "a"], ordered=True) >>> pd.read_csv(StringIO(data), dtype={"col1": dtype}).dtypes # col1 category # col2 object # col3 int64 # dtype: object
При использовании dtype=CategoricalDtype
, "неожиданные" значения за пределами dtype.categories
рассматриваются как отсутствующие значения.
# значение 'c' - не указано >>> dtype = CategoricalDtype(["a", "b", "d"]) >>> pd.read_csv(StringIO(data), dtype={"col1": dtype}).col1 # 0 a # 1 a # 2 NaN # Name: col1, dtype: category # Categories (3, object): ['a', 'b', 'd']
Примечание. При использовании
dtype='category'
результирующие категории всегда будут анализироваться как строки (dtype: object
). Если категории являются числовыми, то их можно преобразовать с помощью функцииpandas.to_numeric()
или, при необходимости, другого преобразователя, напримерpandas.to_datetime()
.Если
dtype=CategoricalDtype(...)
с однородными категориями (все числа, все даты/время и т.д.), то преобразование выполняется автоматически.>>> df = pd.read_csv(StringIO(data), dtype="category") >>> df.dtypes # col1 category # col2 category # col3 category # dtype: object >>> df["col3"] # 0 1 # 1 2 # 2 3 # Name: col3, dtype: category # Categories (3, object): ['1', '2', '3'] >>> new_categories = pd.to_numeric(df["col3"].cat.categories) >>> df["col3"] = df["col3"].cat.rename_categories(new_categories) >>> df["col3"] # 0 1 # 1 2 # 2 3 # Name: col3, dtype: category # Categories (3, int64): [1, 2, 3]
names
и header
)Файл может иметь или не иметь строку заголовка. Библиотека pandas
предполагает, что первая строка должна использоваться в качестве имен столбцов:
>>> data = "a,b,c\n1,2,3\n4,5,6\n7,8,9" >>> print(data) # a,b,c # 1,2,3 # 4,5,6 # 7,8,9 >>> pd.read_csv(StringIO(data)) # a b c # 0 1 2 3 # 1 4 5 6 # 2 7 8 9
Указывая аргумент names
вместе с header
, можно указать другие имена, а также указать, следует ли "выбрасывать" строку заголовка (если таковая имеется):
>>> pd.read_csv(StringIO(data), names=["foo", "bar", "baz"], header=0) # foo bar baz # 0 1 2 3 # 1 4 5 6 # 2 7 8 9 >>> pd.read_csv(StringIO(data), names=["foo", "bar", "baz"], header=None) # foo bar baz # 0 a b c # 1 1 2 3 # 2 4 5 6 # 3 7 8 9
Если заголовок находится НЕ в первой строке, то нужно передать номер этой строки в аргумент header
. Это пропустит предыдущие строки:
>>> data = "skip this skip it\na,b,c\n1,2,3\n4,5,6\n7,8,9" >>> print(data) # skip this skip it # a,b,c # 1,2,3 # 4,5,6 # 7,8,9 >>> pd.read_csv(StringIO(data), header=1) # a b c # 0 1 2 3 # 1 4 5 6 # 2 7 8 9
Примечание. Поведение по умолчанию заключается в выводе имен столбцов: если имена столбцов не передаются, то поведение идентично
header=0
, а имена столбцов выводятся из первой непустой строки файла. Если имена столбцов передаются явно, то поведение идентичноheader=None
.
Если заголовок столбцов в файле содержат повторяющиеся имена, то pandas
по умолчанию различит их, и предотвратит перезапись данных:
>>> data = "a,b,a\n0,1,2\n3,4,5" >>> print(data) # a,b,a # 0,1,2 # 3,4,5 >>> pd.read_csv(StringIO(data)) # a b a.1 # 0 0 1 2 # 1 3 4 5
Повторяющиеся столбцы ‘X’
, ..., ‘X’
становятся ‘X’
, ‘X.1’
, ..., ‘X.N’
.
usecols
)Аргумент usecols
позволяет выбрать любое подмножество столбцов в файле, используя имена столбцов или номера позиций, либо вызываемый объект:
>>> data = "a,b,c,d\n1,2,3,foo\n4,5,6,bar\n7,8,9,baz" >>> print(data) # a,b,c,d # 1,2,3,foo # 4,5,6,bar # 7,8,9,baz >>> pd.read_csv(StringIO(data)) # a b c d # 0 1 2 3 foo # 1 4 5 6 bar # 2 7 8 9 baz >>> pd.read_csv(StringIO(data), usecols=["b", "d"]) # b d # 0 2 foo # 1 5 bar # 2 8 baz >>> pd.read_csv(StringIO(data), usecols=[0, 2, 3]) # a c d # 0 1 3 foo # 1 4 6 bar # 2 7 9 baz >>> pd.read_csv(StringIO(data), usecols=lambda x: x.upper() in ["A", "C"]) # a c # 0 1 3 # 1 4 6 # 2 7 9
Аргумент usecols
также можно использовать, чтобы указать, какие столбцы нужно исключить:
>>> pd.read_csv(StringIO(data), usecols=lambda x: x not in ["a", "c"]) # b d # 0 2 foo # 1 5 bar # 2 8 baz
comment
)Если указан аргумент comment
, то полностью закомментированные строки будут игнорироваться. По умолчанию полностью пустые строки также будут игнорироваться.
>>> data = "\na,b,c\n \n# commented line\n1,2,3\n\n4,5,6" >>> print(data) # # a,b,c # # # commented line # 1,2,3 # # 4,5,6 >>> pd.read_csv(StringIO(data), comment="#") # a b c # 0 1 2 3 # 1 4 5 6
Иногда комментарии или метаданные могут быть помещены в строку с данными:
data = ( "ID,level,category\n" "Patient1,123000,x # really unpleasant\n" "Patient2,23000,y # wouldn't take his medicine\n" "Patient3,1234018,z # awesome" ) with open("tmp.csv", "w") as fh: fh.write(data)
По умолчанию анализатор включает комментарии в выходные данные:
>>> df = pd.read_csv("tmp.csv") >>> df # ID level category # 0 Patient1 123000 x # really unpleasant # 1 Patient2 23000 y # wouldn't take his medicine # 2 Patient3 1234018 z # awesome
Можно подавить комментарии, используя аргумент comment
:
>>> df = pd.read_csv("tmp.csv", comment="#") >>> df # ID level category # 0 Patient1 123000 x # 1 Patient2 23000 y # 2 Patient3 1234018 z
skiprows
и skip_blank_lines
)Если аргумент skip_blank_lines=False
, то read_csv()
не будет игнорировать пустые строки:
>>> data = "a,b,c\n\n1,2,3\n\n\n4,5,6" >>> print(data) # a,b,c # # 1,2,3 # # # 4,5,6 >>> pd.read_csv(StringIO(data), skip_blank_lines=False) # a b c # 0 NaN NaN NaN # 1 1.0 2.0 3.0 # 2 NaN NaN NaN # 3 NaN NaN NaN # 4 4.0 5.0 6.0
Предупреждение. Наличие игнорируемых строк может создавать неоднозначности, связанные с номерами строк. Аргумент
header
использует номера строк (игнорируя закомментированные/пустые строки), в то время какskiprows
использует номера строк (включая закомментированные/пустые строки):>>> data = "#comment\na,b,c\nA,B,C\n1,2,3" >>> print(data) # #comment # a,b,c # A,B,C # 1,2,3 >>> pd.read_csv(StringIO(data), comment="#", header=1) # A B C # 0 1 2 3 >>> data = "A,B,C\n#comment\na,b,c\n1,2,3" >>> print(data) # A,B,C # #comment # a,b,c # 1,2,3 >>> pd.read_csv(StringIO(data), comment="#", skiprows=2) # a b c # 0 1 2 3
Если указаны как header
, так и skiprows
, то header
будет располагаться относительно конца skiprows
. Например:
data = ( "# empty\n" "# second empty line\n" "# third emptyline\n" "X,Y,Z\n" "1,2,3\n" "A,B,C\n" "1,2.,4.\n" "5.,NaN,10.0\n" ) >>> pd.read_csv(StringIO(data), comment="#", skiprows=4, header=1) # A B C # 0 1.0 2.0 4.0 # 1 5.0 NaN 10.0
index_col
)Если в файле на один столбец данных больше, чем количество имен столбцов, первый столбец будет использоваться в качестве индексных меток строк DataFrame
:
>>> data = "a,b,c\n4,apple,bat,5.7\n8,orange,cow,10" >>> pd.read_csv(StringIO(data)) # a b c # 4 apple bat 5.7 # 8 orange cow 10.0
Можно добиться такого поведения, используя аргумент index_col
.
>>> data = "index,a,b,c\n4,apple,bat,5.7\n8,orange,cow,10" >>> pd.read_csv(StringIO(data), index_col=0) # a b c # index # 4 apple bat 5.7 # 8 orange cow 10.0
Есть несколько исключительных случаев, когда файл был подготовлен с разделителями в конце каждой строки данных, что сбивает с толку анализатор. Чтобы явно отключить столбец индекса и отбросить последний столбец, нужно установить index_col=False
:
>>> data = "a,b,c\n4,apple,bat,\n8,orange,cow," # обратите внимание на запятую # в конце каждой строки с данными >>> print(data) # a,b,c # 4,apple,bat, # 8,orange,cow, >>> pd.read_csv(StringIO(data)) # a b c # 4 apple bat NaN # 8 orange cow NaN >>> pd.read_csv(StringIO(data), index_col=False) # a b c # 0 4 apple bat # 1 8 orange cow
Если подмножество данных анализируется с использованием аргумента usecols
, то аргумент index_col
основан на этом подмножестве, а не на исходных данных.
>>> pd.read_csv(StringIO(data), usecols=["b", "c"]) # b c # 4 bat NaN # 8 cow NaN >>> pd.read_csv(StringIO(data), usecols=["b", "c"], index_col=0) # b c # 4 bat NaN # 8 cow NaN
Так же смотрите далее подраздел "Чтение данных с
MultiIndex
"
parse_dates
)Для упрощения работы с данными datetime
функция read_csv()
использует аргументы parse_dates
и date_format
, позволяющие пользователям указывать различные столбцы и форматы даты/времени
для преобразования входных текстовых данных в объекты datetime
.
Самый простой случай - просто передать parse_dates=True
:
with open("foo.csv", mode="w") as f: f.write("date,A,B,C\n20090101,a,1,2\n20090102,b,3,4\n20090103,c,4,5") >>> df = pd.read_csv("foo.csv", index_col=0, parse_dates=True) >>> df # A B C # date # 2009-01-01 a 1 2 # 2009-01-02 b 3 4 # 2009-01-03 c 4 5 >>> df.index # DatetimeIndex(['2009-01-01', '2009-01-02', '2009-01-03'], # dtype='datetime64[ns]', name='date', freq=None)
Бывает так, что сырые данные хранят различные компоненты даты/времени в различных столбцах. Аргумент parse_dates
можно использовать для указания комбинации столбцов для анализа дат и/или времени.
data = ( "KORD,19990127, 19:00:00, 18:56:00, 0.8100\n" "KORD,19990127, 20:00:00, 19:56:00, 0.0100\n" "KORD,19990127, 21:00:00, 20:56:00, -0.5900\n" "KORD,19990127, 21:00:00, 21:18:00, -0.9900\n" "KORD,19990127, 22:00:00, 21:56:00, -0.5900\n" "KORD,19990127, 23:00:00, 22:56:00, -0.5900" ) # пишем данные во временный файл with open("tmp.csv", "w") as fh: fh.write(data) # читаем с указанием позиций столбцов, содержащих # дату и время как вложенные списки (устарело с версии 2.2) >>> df = pd.read_csv("tmp.csv", header=None, parse_dates=[[1, 2], [1, 3]]) >>> df # 1_2 1_3 0 4 # 0 1999-01-27 19:00:00 1999-01-27 18:56:00 KORD 0.81 # 1 1999-01-27 20:00:00 1999-01-27 19:56:00 KORD 0.01 # 2 1999-01-27 21:00:00 1999-01-27 20:56:00 KORD -0.59 # 3 1999-01-27 21:00:00 1999-01-27 21:18:00 KORD -0.99 # 4 1999-01-27 22:00:00 1999-01-27 21:56:00 KORD -0.59 # 5 1999-01-27 23:00:00 1999-01-27 22:56:00 KORD -0.59
Предупреждение на будущее: поддержка вложенных последовательностей для аргумента 'parse_dates' будет считаться устаревшей с версии
pandas
2.2. Теперь для объединения нужных столбцов необходимо использовать функциюpandas.to_datetime()
после синтаксического анализа.
По умолчанию синтаксический анализатор удаляет столбцы даты компонента, но можно сохранить их с помощью ключевого аргумента keep_date_col
(устарело с pandas
2.2 и будет удалено в будущей версии):
df = pd.read_csv( "tmp.csv", header=None, parse_dates=[[1, 2], [1, 3]], keep_date_col=True ) >>> df # 1_2 1_3 0 1 2 3 4 # 0 1999-01-27 19:00:00 1999-01-27 18:56:00 KORD 19990127 19:00:00 18:56:00 0.81 # 1 1999-01-27 20:00:00 1999-01-27 19:56:00 KORD 19990127 20:00:00 19:56:00 0.01 # 2 1999-01-27 21:00:00 1999-01-27 20:56:00 KORD 19990127 21:00:00 20:56:00 -0.59 # 3 1999-01-27 21:00:00 1999-01-27 21:18:00 KORD 19990127 21:00:00 21:18:00 -0.99 # 4 1999-01-27 22:00:00 1999-01-27 21:56:00 KORD 19990127 22:00:00 21:56:00 -0.59 # 5 1999-01-27 23:00:00 1999-01-27 22:56:00 KORD 19990127 23:00:00 22:56:00 -0.59
Обратите внимание: если нужно объединить несколько столбцов в один столбец даты, необходимо использовать вложенный список. Другими словами, parse_dates=[1, 2]
указывает, что второй и третий столбцы должны анализироваться как отдельные столбцы даты, а parse_dates=[[1, 2]]
означает, что два столбца должны быть проанализированы как один столбец.
Также можно использовать словарь для настройки имен столбцов с датами:
>>> date_spec = {"nominal": [1, 2], "actual": [1, 3]} >>> df = pd.read_csv("tmp.csv", header=None, parse_dates=date_spec) >>> df # nominal actual 0 4 # 0 1999-01-27 19:00:00 1999-01-27 18:56:00 KORD 0.81 # 1 1999-01-27 20:00:00 1999-01-27 19:56:00 KORD 0.01 # 2 1999-01-27 21:00:00 1999-01-27 20:56:00 KORD -0.59 # 3 1999-01-27 21:00:00 1999-01-27 21:18:00 KORD -0.99 # 4 1999-01-27 22:00:00 1999-01-27 21:56:00 KORD -0.59 # 5 1999-01-27 23:00:00 1999-01-27 22:56:00 KORD -0.59
Примечание. Если столбец или индекс содержит неразбираемую дату, то весь столбец или индекс будет возвращен без изменений. Для нестандартного анализа даты и времени необходимо использовать функцию
pandas.to_datetime()
послеpandas.read_csv()
.Примечание. Функция
pandas.read_csv()
имеет сверхбыстрый метод анализа строк даты и времени в формате iso8601, например'2000-01-01T00:01:02+00:00'
и подобных вариациях. Если есть возможность организовать хранение данных в этом формате, то время загрузки будет значительно быстрее, примерно в 20 раз!!!
date_format
)Наконец, анализатор позволяет указать пользовательский формат date_format
. С точки зрения производительности, следует попробовать эти методы анализа дат по порядку:
date_format
, например: date_format='%d/%m/%Y'
или date_format={имя_столбца: '%d/%m/%Y'}
.utc
), то следует сначала прочитать данные как dtype: object
, а затем, для преобразования использовать функцию pandas.to_datetime()
.dayfirst
)Несколько примеров строк с датой и времени, которые pandas
автоматически распознает при чтении "сырых данных" (все они представляют 30 декабря 2023 г., 00:00:00):
'20231230'
;'2023/12/30'
;'20231230 00:00:00'
;'30.12.2023 00:00:00'
;'30/Dec/2023 00:00:00'
;'30/December/2023 00:00:00'
;Обратите внимание, что вывод формата чувствителен к значению аргумента
dayfirst
. Еслиdayfirst=True
, то предполагается, что'12.01.2023'
будет 1 декабря. Еслиdayfirst=False
(по умолчанию), то предполагается, что'12.01.2023'
будет 12 января.pandas
попытается угадать формат по первому элементу, отличному отNaN
, а затем проанализирует остальную часть столбца с этим форматом. Еслиpandas
не угадает формат, то будет выдано предупреждение, и каждая строка будет анализироваться индивидуально с помощьюdateutil.parser.parse
. В общем, самый безопасный способ анализа - это явно указать формат даты/времени в аргументеformat
.
df = pd.read_csv( "foo.csv", index_col=0, parse_dates=True, ) >>> df # A B C # date # 2009-01-01 a 1 2 # 2009-01-02 b 3 4 # 2009-01-03 c 4 5
Если в одном столбце данные содержат смешанные форматы даты/времени, то можно попробовать передать format='mixed'
>>> from io import StringIO >>> data = StringIO("date\n12 Jan 2000\n2000-01-13\n") >>> df = pd.read_csv(data) >>> df['date'] = pd.to_datetime(df['date'], format='mixed') >>> df # date # 0 2000-01-12 # 1 2000-01-13
или, если все форматы даты/времени соответствуют ISO8601, но не одинаково отформатированы:
>>> data = StringIO("date\n2020-01-01\n2020-01-01 03:00\n") >>> df = pd.read_csv(data) >>> df['date'] = pd.to_datetime(df['date'], format='ISO8601') >>> df # date # 0 2020-01-01 00:00:00 # 1 2020-01-01 03:00:00
float
Чтобы использовать определенный преобразователь значений float
во время анализа можно указать аргумент float_precision
. Возможные варианты: None
, high
и round_trip
(который гарантированно возвращает значения туда и обратно после записи в файл). Например:
>>> val = "0.3066101993807095471566981359501369297504425048828125" >>> data = "a,b,c\n1,2,{0}".format(val) >>> df = pd.read_csv(StringIO(data), engine="c", float_precision=None) >>> abs(df["c"][0] - float(val)) # 5.551115123125783e-17 >>> df = pd.read_csv(StringIO(data), engine="c", float_precision='high') >>> abs(df["c"][0] - float(val)) # 5.551115123125783e-17 >>> df = pd.read_csv(StringIO(data), engine="c", float_precision='round_trip') >>> abs(df["c"][0] - float(val)) # 0.0
thousands
)Для больших чисел, записанных через разделитель тысяч, можно установить ключевой аргумент thousands
в строку длиной 1, чтобы целые числа обрабатывались правильно:
По умолчанию числа с разделителем тысяч будут обрабатываться как строки:
data = ( "ID|level|category\n" "Patient1|123,000|x\n" "Patient2|23,000|y\n" "Patient3|1,234,018|z" ) with open("tmp.csv", "w") as fh: fh.write(data) >>> df = pd.read_csv("tmp.csv", sep="|") >>> df # ID level category # 0 Patient1 123,000 x # 1 Patient2 23,000 y # 2 Patient3 1,234,018 z >>> df.level.dtype # dtype('O')
Аргумент thousands
позволяет корректно анализировать целые числа:
>>> df = pd.read_csv("tmp.csv", sep="|", thousands=",") >>> df # ID level category # 0 Patient1 123000 x # 1 Patient2 23000 y # 2 Patient3 1234018 z >>> df.level.dtype # dtype('int64')
NA
при чтении данных (аргумент na_values
)Чтобы контролировать, какие значения анализируются как пропущенные, необходимо указать строку в поле na_values
. Если указать список строк, то все значения в нем считаются пропущенными значениями. Если указать число (float
, например 5.0, или целое число, например 5), то соответствующие эквивалентные значения также будут подразумевать пропущенное значение (в этом случае эффективно [5.0, 5]
распознаются как NaN
).
Чтобы полностью переопределить значения по умолчанию, которые распознаются как отсутствующие, необходимо указать аргументу keep_default_na=False
.
Несколько абстрактных примеров:
# числа 5 и 5.0 будут распознаны как `NaN`, # в дополнение к значениям по умолчанию. pd.read_csv("path_to_file.csv", na_values=[5]) # ТОЛЬКО пустое поле будет распознано как `NaN`. pd.read_csv("path_to_file.csv", keep_default_na=False, na_values=[""]) # ТОЛЬКО строки `NA`, и `0` будут распознаны как `NaN`. pd.read_csv("path_to_file.csv", keep_default_na=False, na_values=["NA", "0"]) # строке 'Nope' в дополнение к значениям # по умолчанию распознаются как `NaN`. pd.read_csv("path_to_file.csv", na_values=["Nope"])
true_values
и false_values
)Все обычные значения True
, False
, TRUE
и FALSE
распознаются как логические. Иногда может потребоваться распознать другие значения как логические. Для этого используйте параметры true_values
и false_values
следующим образом:
>>> data = "a,b,c\n1,Yes,2\n3,No,4" >>> print(data) # a,b,c # 1,Yes,2 # 3,No,4 >>> pd.read_csv(StringIO(data)) # a b c # 0 1 Yes 2 # 1 3 No 4 >>> pd.read_csv(StringIO(data), true_values=["Yes"], false_values=["No"]) # a b c # 0 1 True 2 # 1 3 False 4
on_bad_lines
)Некоторые файлы могут содержать искаженные строки со слишком малым или слишком большим количеством полей с данными. Строки со слишком малым количеством полей будут иметь значения NA
, заполненные в завершающих полях. Строки со слишком большим количеством полей по умолчанию выдадут сообщение об ошибке:
>>> data = "a,b,c\n1,2,3\n4,5,6,7\n8,9,10" >>> pd.read_csv(StringIO(data)) # Traceback (most recent call last): # ... # pandas.errors.ParserError: Error tokenizing data. C error: Expected 3 fields in line 3, saw 4
В подобных случаях можно выбрать пропуск плохих строк:
>>> data = "a,b,c\n1,2,3\n4,5,6,7\n8,9,10" >>> pd.read_csv(StringIO(data), on_bad_lines="skip") # a b c # 0 1 2 3 # 1 8 9 10
Или передать вызываемую функцию для обработки ошибочной строки, если анализатор установлен как engine='python'
.
# определим переменную и функцию обработки строк external_list = [] def bad_lines_func(line): external_list.append(line) return line[-3:]
Вызываемая функция bad_lines_func()
будет обрабатывать только строку со слишком большим количеством полей. Неправильные строки, вызванные другими ошибками, будут автоматически пропущены.
>>> bad_lines_func = lambda line: print(line) >>> data = 'name,type\nname a,a is of type a\nname b,"b\" is of type b"' >>> print(data) # name,type # name a,a is of type a # name b,"b" is of type b" >>> pd.read_csv(StringIO(data), on_bad_lines=bad_lines_func, engine="python") # name type # 0 name a a is of type a
Можно использовать аргумент usecols
для удаления посторонних данных, которые появляются в одних строках, но не появляются в других:
>>> pd.read_csv(StringIO(data), usecols=[0, 1, 2]) # Traceback (most recent call last): # ... # ValueError: Usecols do not match columns, columns expected but not found: [0, 1, 2]
Если необходимо сохранить все данные, включая строки со слишком большим количеством полей, то можно указать достаточное количество имен столбцов. Это гарантирует, что строки с недостаточным количеством столбцов будут заполнены символом NaN
.
>>> pd.read_csv(StringIO(data), names=['a', 'b', 'c', 'd']) # a b c d # 0 name type NaN NaN # 1 name a a is of type a NaN NaN # 2 name b b is of type b" NaN NaN
dialect
Ключевой аргумент dialect
предоставляет большую гибкость при указании формата файла. По умолчанию используется диалект Excel
, но можно указать либо название диалекта, либо экземпляр csv.Dialect
.
Предположим, есть данные с незавершенными кавычками:
>>> data = "label1,label2,label3\n" 'index1,"a,c,e\n' "index2,b,d,f" >>> print(data) # label1,label2,label3 # index1,"a,c,e # index2,b,d,f
По умолчанию используется диалект Excel и двойная кавычка обрабатывается как символ кавычки, что приводит к сбою при поиске новой строки до того, как будет найдена закрывающая двойная кавычка.
Такое поведение можно обойти, используя диалект:
>>> import csv >>> dia = csv.excel() >>> dia.quoting = csv.QUOTE_NONE >>> pd.read_csv(StringIO(data), dialect=dia) # label1 label2 label3 # index1 "a c e # index2 b d f
Все параметры диалекта могут быть указаны отдельно, с помощью дополнительных ключевых аргументов:
>>> data = "a,b,c~1,2,3~4,5,6" >>> pd.read_csv(StringIO(data), lineterminator="~") # a b c # 0 1 2 3 # 1 4 5 6
escapechar
)Кавычки (и другие управляющие символы) во встроенных полях могут обрабатываться любым количеством способов. Один из способов - использовать обратную косую черту. Чтобы правильно проанализировать такие данные, необходимо передать аргумент escapechar
:
>>> data = 'a,b\n"hello, \\"Bob\\", nice to see you",5' >>> print(data) # a,b # "hello, \"Bob\", nice to see you",5 >>> pd.read_csv(StringIO(data), escapechar="\\") # a b # 0 hello, "Bob", nice to see you 5
Рассмотрим файл, в заголовке которого на один столбец меньше, чем количество столбцов с данными. В этом особом случае функция read_csv()
предполагает, что первый столбец должен использоваться в качестве индекса:
>>> data = "A,B,C\n20090101,a,1,2\n20090102,b,3,4\n20090103,c,4,5" >>> print(data) # A,B,C # 20090101,a,1,2 # 20090102,b,3,4 # 20090103,c,4,5 # запишем данные with open("foo.csv", "w") as f: f.write(data) # читаем >>> pd.read_csv("foo.csv") # A B C # 20090101 a 1 2 # 20090102 b 3 4 # 20090103 c 4 5
Обратите внимание, что даты не анализировались автоматически. В этом случае нужно будет сделать, как раньше:
>>> df = pd.read_csv("foo.csv", parse_dates=True) >>> df # A B C # 2009-01-01 a 1 2 # 2009-01-02 b 3 4 # 2009-01-03 c 4 5
MultiIndex
Предположим, есть данные, проиндексированные по двум столбцам:
>>> data = 'year,indiv,zit,xit\n1977,"A",1.2,.6\n1977,"B",1.5,.5' >>> print(data) # year,indiv,zit,xit # 1977,"A",1.2,.6 # 1977,"B",1.5,.5 with open("mindex_ex.csv", mode="w") as f: f.write(data)
Аргумент index_col
может принимать список номеров столбцов, чтобы создавать MultiIndex
для индекса возвращаемого объекта:
>>> df = pd.read_csv("mindex_ex.csv", index_col=[0, 1]) >>> df # zit xit # year indiv # 1977 A 1.2 0.6 # B 1.5 0.5 >>> df.loc[1977] # zit xit # indiv # A 1.2 0.6 # B 1.5 0.5
Указав список расположений строк для аргумента header, можно прочитать MultiIndex
для столбцов. При указании непоследовательных строк промежуточные строки будут пропущены.
>>> mi_idx = pd.MultiIndex.from_arrays([[1, 2, 3, 4], list("abcd")], names=list("ab")) >>> mi_col = pd.MultiIndex.from_arrays([[1, 2], list("ab")], names=list("cd")) >>> df = pd.DataFrame(np.ones((4, 2)), index=mi_idx, columns=mi_col) >>> import numpy as np >>> df = pd.DataFrame(np.ones((4, 2)), index=mi_idx, columns=mi_col) >>> df.to_csv("mi.csv") >>> print(open("mi.csv").read()) # c,,1,2 # d,,a,b # a,b,, # 1,a,1.0,1.0 # 2,b,1.0,1.0 # 3,c,1.0,1.0 # 4,d,1.0,1.0 >>> pd.read_csv("mi.csv", header=[0, 1, 2, 3], index_col=[0, 1]) # c 1 2 # d a b # a Unnamed: 2_level_2 Unnamed: 3_level_2 # 1 1.0 1.0 # 2 b 1.0 1.0 # 3 c 1.0 1.0 # 4 d 1.0 1.0
Функция read_csv()
также может интерпретировать более распространенный формат многостолбцовых индексов.
>>> data = ",a,a,a,b,c,c\n,q,r,s,t,u,v\none,1,2,3,4,5,6\ntwo,7,8,9,10,11,12" >>> print(data) # ,a,a,a,b,c,c # ,q,r,s,t,u,v # one,1,2,3,4,5,6 # two,7,8,9,10,11,12 with open("mi2.csv", "w") as fh: fh.write(data) >>> pd.read_csv("mi2.csv", header=[0, 1], index_col=0) # a b c # q r s t u v # one 1 2 3 4 5 6 # two 7 8 9 10 11 12
Примечание. Если
index_col
не указан (например, нет индекса или он записан с помощьюdf.to_csv(..., index=False)
, то все имена в индексе столбцов будут потеряны.
chunksize
и iterator
)Предположим, что необходимо "лениво" перебирать файл (потенциально очень большой), а не считывать весь файл в память, например:
>>> df = pd.DataFrame(np.random.randn(10, 4)) >>> df.to_csv("tmp.csv", index=False)
Если указать размер фрагмента (аргумент chunksize
), то возвращаемое значение будет итерируемым объектом типа TextFileReader
:
with pd.read_csv("tmp.csv", chunksize=4) as reader: print(reader) for chunk in reader: print(chunk) # <pandas.io.parsers.readers.TextFileReader object at 0x7f1e31b73670> # 0 1 2 3 # 0 0.895552 -0.158974 0.107887 -0.621232 # 1 0.626029 1.758114 1.342532 0.146105 # 2 1.294353 -0.258822 0.547958 -1.357659 # 3 -0.128099 -0.510162 0.283735 -0.410268 # 0 1 2 3 # 4 -0.732997 0.411201 -1.570236 -2.267693 # 5 0.082201 -1.406110 0.265344 0.959789 # 6 -0.437544 1.769002 -0.813527 -1.738977 # 7 -0.680272 -0.729672 0.890892 1.218180 # 0 1 2 3 # 8 0.806144 0.434089 1.362968 0.634899 # 9 0.604131 -1.290217 0.673257 -1.376953
Передача аргумента iterator=True
также вернет объект TextFileReader
:
with pd.read_csv("tmp.csv", iterator=True) as reader: print(reader.get_chunk(5)) # 0 1 2 3 # 0 0.895552 -0.158974 0.107887 -0.621232 # 1 0.626029 1.758114 1.342532 0.146105 # 2 1.294353 -0.258822 0.547958 -1.357659 # 3 -0.128099 -0.510162 0.283735 -0.410268 # 4 -0.732997 0.411201 -1.570236 -2.267693