Автор оригинала: Olivera Popović.
Вступление
Pandas – библиотека Python с открытым исходным кодом для анализа данных. Она предназначена для эффективной и интуитивной обработки структурированных данных.
Двумя основными структурами данных в Pandas являются Series (Ряды) и DataFrame. Ряды являются по существу одномерными маркированными массивами любого типа данных, в то время как DataFrames являются двумерными, с потенциально гетерогенными типами данных, маркированными массивами любого типа данных. Гетерогенный означает, что не все «ряды» должны быть одинакового размера.
В этой статье мы рассматрим наиболее распространенные способы создания DataFrame и методы изменения их структуры.
Мы будем использовать блокнот Jupyter, так как он предлагает хорошее визуальное представление DataFrames. Однако любая среда IDE также выполнит эту работу, просто вызвав инструкцию print() для объекта DataFrame.
Создание DataFrame
Каждый раз, когда создается DataFrame, независимо от того, создается ли он вручную или создается из источника данных, например файла, данные должны упорядочиваться в табличном виде как последовательности строк с данными.
Это означает, что строки имеют одинаковый порядок полей, т.е. если требуется DataFrame с информацией об имени и возрасте человека, необходимо убедиться, что все строки содержат информацию одинаково.
Любое несоответствие приведет к тому, что DataFrame будет неисправен, что приведет к ошибкам.
Создание пустого DataFrame
Создать пустой DataFrame
так же просто, как:
import pandas as pd dataFrame1 = pd.DataFrame()
Рассмотрим, как можно добавлять строки и столбцы в этот пустой DataFrame при управлении их структурой.
Создание DataFrame из списков
Следуя принципу «последовательность строк с одинаковым порядком полей», можно создать DataFrame из списка, который содержит такую последовательность, или из нескольких списков объединённых вместе функцией zip() таким образом, что они обеспечивают последовательность так:
import pandas as pd listPepper = [ [50, "Bell pepper", "Not even spicy"], [5000, "Espelette pepper", "Uncomfortable"], [500000, "Chocolate habanero", "Practically ate pepper spray"] ] dataFrame1 = pd.DataFrame(listPepper) dataFrame1 # If you aren't using Jupyter, you'll have to call `print()` # print(dataFrame1)
Это приводит к:
Такого же эффекта можно было бы достичь, если бы данные находились в нескольких списках и были объединены вместе с помощью zip(). Этот подход может быть использован, когда данные, которые мы имеем, предоставляются в виде списков значений для одного столбца (поля), вместо вышеупомянутого способа, в котором список содержит данные для каждой конкретной строки.
Это означает, что у нас есть все данные (по порядку) для столбцов по отдельности, которые, будучи сжатыми вместе, создают строки.
Возможно, вы заметили, что метки столбцов и строк не очень информативны в созданном нами DataFrame. Можно передать эту информацию при создании DataFrame.
import pandas as pd listScoville = [50, 5000, 500000] listName = [ "Bell pepper", "Espelette pepper", "Chocolate habanero" ] listFeeling = [ "Not even spicy", "Uncomfortable", "Practically ate pepper spray" ] columns = ['Scoville', 'Name', 'Feeling'] dataFrame1 = pd.DataFrame(zip(listScoville, listName, listFeeling), columns=columns) # Print the dataframe dataFrame1
Что даёт нам тот же результат, что и раньше, только с более значимыми именами столбцов:
Другим представлением данных, которое можно использовать здесь, является предоставление данных в виде списка словарей в следующем формате:
listPepper = [ { columnName1 : valueForRow1, columnName2: valueForRow1, ... }, { columnName1 : valueForRow2, columnName2: valueForRow2, ... }, ... ]
В нашем примере представление будет выглядеть следующим образом:
listPepper = [ {'Scoville' : 50, 'Name' : 'Bell pepper', 'Feeling' : 'Not even spicy'}, {'Scoville' : 5000, 'Name' : 'Espelette pepper', 'Feeling' : 'Uncomfortable'}, {'Scoville' : 500000, 'Name' : 'Chocolate habanero', 'Feeling' : 'Practically ate pepper spray'}, ]
И мы создадим DataFrame
таким же образом, как и раньше:
dataFrame1 = pd.DataFrame(listPepper)
Создание DataFrame из словарей
Словари являются еще одним способом предоставления данных в виде столбцов. Каждому столбцу присваивается упорядоченный список строк значений.
dictionaryData = { 'columnName1' : [valueForRow1, valueForRow2, valueForRow3...], 'columnName2' : [valueForRow1, valueForRow2, valueForRow3...], .... }
Давайте представим те же данные, что и раньше, но в формате словаря:
import pandas as pd dictionaryData = { 'Scoville' : [50, 5000, 500000], 'Name' : ["Bell pepper", "Espelette pepper", "Chocolate habanero"], 'Feeling' : ["Not even spicy", "Uncomfortable", "Practically ate pepper spray"] } dataFrame1 = pd.DataFrame(dictionaryData) # Print the dataframe dataFrame1
Что дает нам ожидаемый результат:
Чтение DataFrame из файла
Для чтения и записи DataFrames поддерживается множество типов файлов. Каждая функция соответствует типу файла, например read_csv(), read_excel(), read_json(), read_html() и т.д.
Наиболее распространенным типом файла является .csv (значения разделенные запятыми). Строки состоят из значений, разделенных специальным символом (чаще всего запятой). Можно задать другой разделитель с помощью аргумента sep.
Если вы не знакомы с типом файла .csv
, вот пример того, как он выглядит:
Scoville, Name, Feeling 50, Bell pepper, Not even spicy 5.000, Espelette pepper, Uncomfortable 10.000, Serrano pepper, I regret this 60.000, Bird's eye chili, 4th stage of grief 500.000, Chocolate habanero, Practically ate pepper spray 2.000.000, Carolina Reaper, Actually ate pepper spray
Обратите внимание, что первой строкой в файле являются имена столбцов. Конечно, можно указать, с какой строки Pandas должен начать считывать данные, но по умолчанию Pandas рассматривает первую строку как имена столбцов и начинает загрузку данных из второй строки:
import pandas as pd pepperDataFrame = pd.read_csv('pepper_example.csv') # For other separators, provide the `sep` argument # pepperDataFrame = pd.read_csv('pepper_example.csv', sep=';') pepperDataFrame #print(pepperDataFrame)
Что дает нам на выходе:
Манипулирование Фреймами Данных
В этом разделе рассматриваются основные методы изменения структуры DataFrame. Однако прежде чем перейти к этой теме, необходимо знать, как получить доступ к отдельным строкам или группам строк, а также к столбцам.
Доступ/Расположение Элементов
Pandas имеет два разных способа выбора данных – loc[] и iloc[].
loc[] позволяет выбирать строки и столбцы с помощью меток, таких как row[‘Value’] и culumn[‘Other Value’]. В то же время, iloc[] принимает индекс записей, которые вы хотите выбрать, поэтому вы можете использовать только числа. Можно также выбрать столбцы, просто передав их имя в скобки. Посмотрим, как это работает в действии:
# Location by label # Here, '5' is treated as the *label* of the index, not its value print(pepperDataFrame.loc[5]) # Location by index print(pepperDataFrame.iloc[1])
Выход:
Scoville 2.000.000 Name Carolina Reaper Feeling Actually ate pepper spray Name: 5, dtype: object Scoville 5.000 Name Espelette pepper Feeling Uncomfortable Name: 1, dtype: object
Это также работает для группы строк, от 0 до n:
print(pepperDataFrame.loc[:1])
Это выводит:
Важно отметить, что iloc[]
всегда ожидает целое число. loc[]
поддерживает и другие типы данных. Здесь мы также можем использовать целое число на ряду с другими типами данных, например строки.
Также можно получить доступ к определенным значениям для элементов. Например, может потребоваться получить доступ к элементу во 2-й строке, но вернуть только его значение Name:
print(pepperDataFrame.loc[2, 'Name'])
Это возвращает:
Chocolate habanero
Доступ к столбцам так же прост, как запись dataFrameName.ColumnName или dataFrameName [‘ColumnName’]. Второй вариант предпочтителен, так как столбец может иметь то же имя, что и зарезервированное имя в Pandas, и использование первого варианта в этом случае может вызвать ошибки:
print(pepperDataFrame['Name']) # Same output as print(pepperDataFrame.Name)
Это выводит:
0 Bell pepper 1 Espelette pepper 2 Chocolate habanero Name: Name, dtype: object
Доступ к столбцам можно также получить с помощью loc[] и iloc[]. Например, мы получим доступ ко всем строкам, начиная с 0…n, где n – количество строк, и выберем первый столбец. Вывод совпадает с выводом предыдущей строки кода:
dataFrame1.iloc[:, 1] # or dataFrame1.loc[:, 'Name']
Манипулирование Индексами
Индексы – это метки строк в DataFrame и именно их мы используем при обращении к строкам. Поскольку мы не изменили индексы по умолчанию, которые Pandas присваивают DataFrame при создании, все наши строки были помечены целыми числами от 0 и выше.
Первый способ изменить индексацию вашего DataFrame
– это использовать метод set_index()
. Мы передаем любой из столбцов в вашем DataFrame
этому методу, и он становится новым индексом. Таким образом, мы можем либо сами создавать индексы, либо просто назначить столбец в качестве индекса.
Обратите внимание, что метод не изменяет исходный DataFrame, а вместо этого возвращает новый DataFrame с новым индексом, поэтому мы должны назначить возвращаемое значение переменной DataFrame, если мы хотим сохранить изменение, или установить флаг inplace равным True:
import pandas as pd listPepper = [ {'Scoville' : 50, 'Name' : 'Bell pepper', 'Feeling' : 'Not even spicy'}, {'Scoville' : 5000, 'Name' : 'Espelette pepper', 'Feeling' : 'Uncomfortable'}, {'Scoville' : 500000, 'Name' : 'Chocolate habanero', 'Feeling' : 'Practically ate pepper spray'}, ] dataFrame1 = pd.DataFrame(listPepper) dataFrame2 = dataFrame1.set_index('Scoville') dataFrame2
Выход:
Это будет работать так же хорошо:
dataFrame1 = pd.DataFrame(listPepper) dataFrame1.set_index('Scoville', inplace=True) dataFrame1
Теперь, когда у нас есть нестандартный индекс, мы можем использовать новый набор значений, используя reindex(), Pandas автоматически заполнит значения NaN для каждого индекса, который не может быть сопоставлен с существующей строкой:
new_index = [50, 5000, 'New value not present in the data frame'] dataFrame1.reindex(new_index)
Выход:
Вы можете контролировать, какое значение Pandas использует для заполнения пропущенных значений, установив необязательный параметр fill_value
:
dataFrame1.reindex(new_index, fill_value=0)
Выход:
Поскольку мы установили новый индекс для нашего DataFrame, loc[] теперь работает с этим индексом:
dataFrame1.loc[5000] # dataFrame1.iloc[5000] outputs the same in this case
Это приводит к:
Name Espelette pepper Feeling Uncomfortable Name: 5000, dtype: object
Манипулирование строками (rows)
Добавление и удаление строк становится простым, если удобно использовать loc[]. Если задать несуществующую строку, она будет создана:
dataFrame1.loc[50] = [10000, 'Serrano pepper', 'I regret this'] dataFrame1
Выход:
И если вы хотите удалить строку, вы указываете ее индекс функции drop ()
. Он принимает необязательный параметр axis
. Ось | принимает
0 /
индекс или
1 /
колонки . В зависимости от этого функция
drop() отбрасывает либо вызываемую строку, либо вызываемый столбец.
Если требуется удалить строку, необходимо указать ее индекс для функции drop(). Она принимает необязательный параметр, axis. Axis может быть 0/index или 1/columns. В зависимости от этого функция drop() удаляет строку или столбец для которого она была вызвана.
Если не указать значение параметра axis
, то соответствующая строка будет удалена по умолчанию, так как axis
0
по умолчанию:
Если не указать значение параметра axis, соответствующая строка будет удалена по умолчанию, так как axis по умолчанию равен 0:
dataFrame1.drop(1, inplace=True) # Same as dataFrame1.drop(1, axis=0)
Выход:
Вы также можете переименовать строки, которые уже существуют в таблице. Функция rename()
принимает словарь изменений, которые вы хотите внести:
dataFrame1.rename({0:"First", 1:"Second"}, inplace=True)
Выход:
Обратите внимание, что drop()
и rename()
также принимают необязательный параметр inplace
. Установка этого параметра в True
( False
по умолчанию) скажет Pandas изменить исходный DataFrame
вместо того, чтобы возвращать новый. Если оставить его не заданным, вам придется упаковать полученный DataFrame
в новый, чтобы сохранить изменения.
Другим полезным методом, о котором следует знать, является функция drop_duplicates(), которая удаляет все повторяющиеся строки из DataFrame. Давайте продемонстрируем это, добавив две повторяющиеся строки:
dataFrame1.loc[3] = [60.000, "Bird's eye chili", "4th stage of grief"] dataFrame1.loc[4] = [60.000, "Bird's eye chili", "4th stage of grief"] dataFrame1
Что дает нам выход:
Теперь мы можем вызвать drop_duplicates()
:
dataFrame1.drop_duplicates(inplace=True) dataFrame1
И дубликаты строк будут удалены:
Манипулирование столбцами (columns)
Новые столбцы можно добавлять аналогично добавлению строк:
dataFrame1['Color'] = ['Green', 'Bright Red', 'Brown'] dataFrame1
Выход:
Также, как и строки, столбцы можно удалить, вызвав функцию drop()
, с той лишь разницей, что вы должны установить необязательный параметр axis
в значение 1
чтобы Pandas знали, что вы хотите удалить столбец, а не строку:
dataFrame1.drop('Feeling', axis=1, inplace=True)
Выход:
Когда речь идет о переименовании столбцов, функции rename() нужно сказать конкретно, что мы хотим изменить столбцы, установив необязательные параметр columns значение нашего “словаря изменений”:
dataFrame1.rename(columns={"Feeling":"Measure of Pain"}, inplace=True)
Выход:
Опять же, как и при удалении/переименовании строк, вы можете установить необязательный параметр на месте
в True
если вы хотите, чтобы исходный DataFrame
был изменен вместо функции, возвращающей новый DataFrame
.
Опять же, как и при удалении/переименовании строк, можно установить для параметра inplace значение True, если требуется изменить исходный DataFrame вместо создания нового DataFrame.
Вывод
В этой статье мы рассмотрели, что такое Pandas DataFrame
s, поскольку они являются ключевым классом из фреймворка Pandas, используемого для хранения данных.
В этой статье мы рассмотрели, что такое Pandas DataFrame, поскольку он является ключевым классом фреймворка Pandas для хранения данных.
Мы научились создавать DataFrame вручную, используя список и словарь, после чего считывали данные из файла.
Затем мы манипулировали данными в DataFrame
– используя loc[]
и iloc[]
, мы находили данные, создавали новые строки и столбцы, переименовывали существующие и затем удаляли их.
Затем мы манипулировали данными в DataFrame используя loc[] и iloc[]. Мы обнаружили данные, создали новые строки и столбцы, переименовали существующие, а затем удалили их.