Рубрики
Без рубрики

Чтение и запись CSV-файлов в Python с Pandas

В статье показано, как читать и писать CSV-файлы с помощью библиотеки Python Pandas. Для чтения CSV-файла используется метод read_csv() библиотеки Pandas. Для записи CSV-файла используется метод to_csv().

Автор оригинала: Guest Contributor.

В то время как вы можете читать и писать CSV-файлы в Python с помощью встроенной функции open() или выделенного модуля csv , вы также можете использовать Pandas.

В этой статье вы увидите, как использовать библиотеку Python Pandas для чтения и записи CSV-файлов.

Что такое CSV-файл?

Давайте быстро рассмотрим, что такое CSV-файл – не более чем простой текстовый файл, следуя нескольким соглашениям по форматированию. Однако это самый распространенный, простой и лёгкий метод хранения табличных данных. Этот формат упорядочивает таблицы, следуя определенной структуре, разделенной на строки и столбцы. Именно эти строки и столбцы содержат ваши данные.

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

Например, у нас может быть таблица, которая выглядит следующим образом:

| City         | State        | Capital | Population    |
| ------------ | ------------ | ------- | ------------- |
| Philadelphia | Pennsylvania | No      | 1.581 Million |
| Sacramento   | California   | Yes     | 0.5 Million   |
| New York     | New York     | No      | 8.623 Million |
| Austin       | Texas        | Yes     | 0.95 Million  |
| Miami        | Florida      | No      | 0.463 Million |

Если бы мы преобразовали её в формат CSV, она выглядела бы следующим образом:

City,State,Capital,Population
Philadelphia,Pennsylvania,No,1.581 Million
Sacramento,California,Yes,0.5 Million
New York,New York,No,8.623 Million
Austin,Texas,Yes,0.95 Million
Miami,Florida,No,0.463 Million

Хотя имя (Comma-Separated Values) изначально использует запятую в качестве разделителя, можно также использовать другие разделители, например точку с запятой (;). Каждая строка таблицы является новой строкой CSV-файла и очень компактным и лаконичным способом представления табличных данных.

Теперь давайте рассмотрим функцию read_csv() .

Чтение и запись CSV-файлов с помощью Pandas

Pandas – это очень мощный и популярный фреймворк для анализа и обработки данных. Одной из наиболее ярких особенностей Pandas является его способность читать и записывать различные типы файлов, включая CSV и Excel. Можно эффективно и легко манипулировать CSV-файлами в Pandas с помощью таких функций, как read_csv() и to_csv().

Установка Pandas

Вам нужно установить Pandas, прежде чем использовать его. Давайте сделаем это с помощью pip :

$ pip install pandas

Чтение CSV-файлов с помощью read_csv()

Давайте импортируем набор данных Titanic, который можно получить на GitHub :

import pandas as pd
titanic_data = pd.read_csv('titanic.csv')

Pandas будет искать этот файл в каталоге скрипта, естественно, и мы просто предоставим путь к файлу, который мы хотели бы разобрать, как единственный и обязательный аргумент этого метода.

Давайте взглянем на head() этого набора данных, чтобы убедиться, что он импортирован правильно:

titanic_data.head()

Это приводит к:

   PassengerId  Survived  Pclass  ...     Fare Cabin  Embarked
0            1         0       3  ...   7.2500   NaN         S
1            2         1       1  ...  71.2833   C85         C
2            3         1       3  ...   7.9250   NaN         S
3            4         1       1  ...  53.1000  C123         S
4            5         0       3  ...   8.0500   NaN         S

Кроме того, вы также можете читать CSV-файлы из онлайн-ресурсов, таких как GitHub, просто передав URL-адрес ресурса функции read_csv() . Давайте прочитаем этот же CSV-файл из репозитория GitHub, не загружая его сначала на нашу локальную машину:

import pandas as pd

titanic_data = pd.read_csv(r'https://raw.githubusercontent.com/datasciencedojo/datasets/master/titanic.csv')
print(titanic_data.head())

Это также приводит к:

   PassengerId  Survived  Pclass  ...     Fare Cabin  Embarked
0            1         0       3  ...   7.2500   NaN         S
1            2         1       1  ...  71.2833   C85         C
2            3         1       3  ...   7.9250   NaN         S
3            4         1       1  ...  53.1000  C123         S
4            5         0       3  ...   8.0500   NaN         S

[5 rows x 12 columns]

Настройка заголовков

По умолчанию метод read_csv() использует первую строку CSV-файла в качестве заголовков столбцов. Иногда эти заголовки могут иметь странные имена, и вы можете захотеть использовать свои собственные заголовки. Вы можете установить заголовки либо после чтения файла, просто назначив поле columns экземпляра DataFrame другому списку, либо вы можете установить заголовки во время чтения CSV в первую очередь.

Давайте определим список имен столбцов и будем использовать их вместо имен из CSV-файла:

import pandas as pd

col_names = ['Id',
             'Survived',
             'Passenger Class',
             'Full Name',
             'Gender',
             'Age',
             'SibSp',
             'Parch',
             'Ticket Number',
             'Price', 'Cabin',
             'Station']

titanic_data = pd.read_csv(r'E:\Datasets\titanic.csv', names=col_names)
print(titanic_data.head())

Давайте запустим этот код:

            Id  Survived Passenger Class  ...    Price  Cabin   Station
0  PassengerId  Survived          Pclass  ...     Fare  Cabin  Embarked
1            1         0               3  ...     7.25    NaN         S
2            2         1               1  ...  71.2833    C85         C
3            3         1               3  ...    7.925    NaN         S
4            4         1               1  ...     53.1   C123         S

Хм, теперь у нас есть наши пользовательские заголовки, но первая строка CSV-файла, которая первоначально использовалась для установки имен столбцов, также включена в DataFrame . Давайте пропустим эту строку, так как она больше не имеет для нас никакого значения.

Пропуск строк при чтении CSV

Давайте решим эту проблему с помощью аргумента skiprows :

import pandas as pd

col_names = ['Id',
             'Survived',
             'Passenger Class',
             'Full Name',
             'Gender',
             'Age',
             'SibSp',
             'Parch',
             'Ticket Number',
             'Price', 'Cabin',
             'Station']

titanic_data = pd.read_csv(r'E:\Datasets\titanic.csv', names=col_names, skiprows=[0])
print(titanic_data.head())

Теперь давайте запустим этот код:

   Id  Survived  Passenger Class  ...    Price Cabin  Station
0   1         0                3  ...   7.2500   NaN        S
1   2         1                1  ...  71.2833   C85        C
2   3         1                3  ...   7.9250   NaN        S
3   4         1                1  ...  53.1000  C123        S
4   5         0                3  ...   8.0500   NaN        S

Работает как по волшебству! Аргумент skiprows принимает список строк, которые вы хотите пропустить. Вы можете пропустить, например, 0, 4, 7 если хотите:

titanic_data = pd.read_csv(r'E:\Datasets\titanic.csv', names=col_names, skiprows=[0, 4, 7])
print(titanic_data.head(10))

Это приведет к тому, что DataFrame не будет содержать некоторые строки, которые мы видели раньше:

   Id  Survived  Passenger Class  ...    Price Cabin  Station
0   1       е  0                3  ...   7.2500   NaN        S
1   2         1                1  ...  71.2833   C85        C
2   3         1                3  ...   7.9250   NaN        S
3   5         0                3  ...   8.0500   NaN        S
4   6         0                3  ...   8.4583   NaN        Q
5   8         0                3  ...  21.0750   NaN        S
6   9         1                3  ...  11.1333   NaN        S
7  10         1                2  ...  30.0708   NaN        C
8  11         1                3  ...  16.7000    G6        S
9  12         1                1  ...  26.5500  C103        S

Имейте в виду, что пропуск строк происходит до того как DataFrame полностью сформирован, поэтому не будет пропущено ни одного индекса самого DataFrame, хотя в этом случае можно увидеть, что в поле Id (импортированном из CSV-файла) отсутствуют идентификаторы 4 и 7.

Удаление Заголовков

Вы также можете решить полностью удалить заголовок, что приведет к DataFrame , который просто имеет 0...n столбцов заголовка, установив аргумент header в None :

Вы также можете захотеть удалить заголовок полностью, что приведет к тому что результирующий DataFrame будет содержать просто 0…n столбцов заголовка. Для этого нужно установить аргумент заголовка None:

titanic_data = pd.read_csv(r'E:\Datasets\titanic.csv', header=None, skiprows=[0])

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

   0   1   2                                                  3       4   ...  7                 8        9 
0   1   0   3                            Braund, Mr. Owen Harris    male  ...   0         A/5 21171   7.2500
1   2   1   1  Cumings, Mrs. John Bradley (Florence Briggs Th...  female  ...   0          PC 17599  71.2833
2   3   1   3                             Heikkinen, Miss. Laina  female  ...   0  STON/O2. 3101282   7.9250
3   4   1   1       Futrelle, Mrs. Jacques Heath (Lily May Peel)  female  ...   0            113803  53.1000
4   5   0   3                           Allen, Mr. William Henry    male  ...   0            373450   8.0500

Указание разделителей

Как уже упоминалось ранее, в конечном итоге вы, вероятно, столкнетесь с CSV-файлом, который на самом деле не использует запятые для разделения данных. В таких случаях можно использовать аргумент sep для указания других разделителей:

titanic_data = pd.read_csv(r'E:\Datasets\titanic.csv', sep=';')

Запись CSV-файлов с помощью to_csv()

Опять же, DataFrame являются табличными. Превратить DataFrame в CSV – файл так же просто, как превратить CSV – файл в DataFrame – мы вызываем функцию write_csv() у экземпляра DataFrame .

При записи DataFrame в CSV-файл вы также можете изменить имена столбцов с помощью аргумента columns или указать разделитель с помощью аргумента sep . Если не указать ни один из них, в конечном итоге будет создан стандартный csv файл, с запятыми в качестве разделителя.

Давайте поиграем с этим:

import pandas as pd
cities = pd.DataFrame([['Sacramento', 'California'], ['Miami', 'Florida']], columns=['City', 'State'])
cities.to_csv('cities.csv')

Здесь мы сделали простой DataFrame с двумя городами и их соответствующими штатами. Затем мы сохранили эти данные в CSV-файл, используя to_csv() предоставив имя файла.

В результате у нас появился новый файл в рабочем каталоге запущенного скрипта, который содержит:

,City,State
0,Sacramento,California
1,Miami,Florida

Хотя это не очень хорошо отформатировано. У нас все еще есть индексы из фрейма данных , который также ставит странное отсутствующее место перед именами столбцов. Если бы мы повторно импортировали этот CSV обратно в DataFrame , это был бы беспорядок:

Хотя, результат не очень хорошо отформатирован. У нас все еще есть индексы из DataFrame, а также странное пустое место перед именами столбцов. Если мы повторно импортируем этот CSV обратно в DataFrame, то получим беспорядок:

df = pd.read_csv('cities.csv')
print(df)

Это приводит к:

   Unnamed: 0        City       State
0           0  Sacramento  California
1           1       Miami     Florida

Индексы из DataFrame в итоге превратились в новый столбец, который теперь Unnamed.

При сохранении файла необходимо обязательно отбросить индекс DataFrame:

import pandas as pd
cities = pd.DataFrame([['Sacramento', 'California'], ['Miami', 'Florida']], columns=['City', 'State'])
cities.to_csv('cities.csv', index=False)

Это приводит к созданию файла, который содержит:

City,State
Sacramento,California
Miami,Florida

Работает как заклинание! Если повторно импортировать его и распечатать содержимое, DataFrame будет построен правильно:

df = pd.read_csv('cities.csv')
print(df)

Это приводит к:

         City       State
0  Sacramento  California
1       Miami     Florida

Настройка заголовков

Давайте изменим заголовки столбцов по умолчанию:

import pandas as pd
cities = pd.DataFrame([['Sacramento', 'California'], ['Miami', 'Florida']], columns=['City', 'State'])
new_column_names = ['City_Name', 'State_Name']
cities.to_csv('cities.csv', index=False, header=new_column_names)

Мы создали список new_header, который содержит различные значения для наших столбцов. Затем, используя аргумент header , мы установили их вместо исходных имен столбцов. Это создает файл cities.csv с таким содержимым:

City_Name,State_Name
Sacramento,California
Miami,Florida
Washington DC,Unknown

Настройка разделителя

Давайте изменим разделитель со значения по умолчанию ( , ) на новый:

import pandas as pd
cities = pd.DataFrame([['Sacramento', 'California'], ['Miami', 'Florida']], columns=['City', 'State'])
cities.to_csv('cities.csv', index=False, sep=';')

В результате получается файл cities.csv , содержащий:

City;State
Sacramento;California
Miami;Florida

Обработка пропущенных значений

Иногда DataFrame имеют пропущенные значения, которые мы оставили как NaN или NA . В таких случаях вы можете отформатировать их при записи в CSV-файл. Вы можете использовать аргумент na_rep и установить значение, которое будет помещено вместо пропущенного значения:

import pandas as pd
cities = pd.DataFrame([['Sacramento', 'California'], ['Miami', 'Florida'], ['Washington DC', pd.NA]], columns=['City', 'State'])
cities.to_csv('cities.csv', index=False, na_rep='Unknown')

Здесь у нас есть две действительные пары город-штат, но Вашингтон, округ Колумбия отсутствует его штат. Если мы запустим этот код, то получим файл cities.csv со следующим содержимым:

Здесь у нас есть две валидные пары город-штат, но у города Вашингтон округ Колумбия отсутствует штат. Если мы запустим этот код, он приведет к cities.csv со следующим содержимым:

City,State
Sacramento,California
Miami,Florida
Washington DC,Unknown

Заключение

В статье показано, как читать и писать CSV-файлы с помощью Python библиотеки Pandas. Для чтения CSV-файла используется метод read_csv(). Можно также передавать пользовательские имена заголовков при чтении CSV-файлов через атрибут names метода read_csv(). Наконец, для записи CSV-файла с помощью Pandas сначала необходимо создать объект Pandas DataFrame, а затем вызвать метод to_csv() у DataFrame.