Вступление
Pandas - это библиотека Python с открытым исходным кодом для анализа данных. Он разработан для эффективной и интуитивно понятной обработки и обработки структурированных данных.
Две основные структуры данных в Pandas - это Series
и DataFrame
.
Series
- это, по сути, одномерные помеченные массивы любого типа
данных, тогда как DataFrame
являются двумерными, с потенциально
гетерогенными типами данных, помеченными массивами любого типа данных.
Гетерогенность означает, что не все «строки» должны быть одинакового
размера.
В этой статье мы рассмотрим наиболее распространенные способы создания
DataFrame
и методы изменения их структуры.
Мы будем использовать Jupyter Notebook, поскольку он предлагает хорошее
визуальное представление DataFrame
s. Тем не менее, любая IDE также
выполнит эту работу, просто вызвав оператор print()
для объекта
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)
Это приводит к:
{.ezlazyload}
Такого же эффекта можно было бы достичь, если бы данные были объединены
в несколько списков и объединены zip()
Этот подход можно использовать,
когда данные, которые у нас есть, представлены в виде списков значений
для одного столбца (поля), вместо вышеупомянутого способа, при котором
список содержит данные для каждой конкретной строки как единицы.
Это означает, что у нас есть все данные (по порядку) для столбцов по отдельности, которые при объединении вместе образуют строки.
Вы могли заметить, что метки столбцов и строк не очень информативны в
DataFrame
нами 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"]
dataFrame1 = pd.DataFrame(zip(listScoville, listName, listFeeling), columns = ['Scoville', 'Name', 'Feeling'])
# Print the dataframe
dataFrame1
Это даст нам тот же результат, что и раньше, только с более значимыми именами столбцов:
{.ezlazyload}
Другое представление данных, которое вы можете использовать здесь, - это предоставить данные в виде списка словарей в следующем формате:
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
Это дает нам ожидаемый результат:
{.ezlazyload}
Чтение DataFrame из файла
Существует много типов файлов, поддерживаемых для чтения и записи
DataFrame
. Каждая соответствующая функция типа файла следует одному и
тому же синтаксису read_filetype()
, например 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)
Что дает нам результат:
{.ezlazyload}
Управление фреймами данных
В этом разделе будут рассмотрены основные методы изменения структуры
DataFrame
. Однако, прежде чем мы перейдем к этой теме, вы должны
знать, как получить доступ к отдельным строкам или группам строк, а
также к столбцам.
Доступ / расположение элементов
У Pandas есть два разных способа выбора данных - loc[]
и iloc[]
.
loc[]
позволяет выбирать строки и столбцы с помощью меток, таких как
row ['Value'] и column ['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])
Это выводит:
{.ezlazyload}
Важно отметить, что iloc[]
всегда ожидает целое число. loc[]
поддерживает другие типы данных. Здесь мы также можем использовать целое
число, хотя мы также можем использовать другие типы данных, такие как
строки.
Вы также можете получить доступ к определенным значениям для элементов.
Например, мы могли бы захотеть получить доступ к элементу во 2-й строке,
но вернуть только его значение Name
print(pepperDataFrame.loc[2, 'Name'])
Это возвращает:
Chocolate habanero
dataFrameName.ColumnName
к столбцам так же просто, как написать
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
Выход:
{.ezlazyload}
Это тоже сработает:
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)
Выход:
{.ezlazyload}
Вы можете контролировать, какое значение Pandas использует для
заполнения отсутствующих значений, установив необязательный параметр
fill_value
:
dataFrame1.reindex(new_index, fill_value=0)
Выход:
{.ezlazyload}
Поскольку мы установили новый индекс для нашего DataFrame
, loc[]
теперь работает с этим индексом:
dataFrame1.loc[5000]
# dataFrame1.iloc[5000] outputs the same in this case
Это приводит к:
Name Espelette pepper
Feeling Uncomfortable
Name: 5000, dtype: object
Управление строками
Добавление и удаление строк становится простым, если вам удобно
использовать loc[]
. Если вы установите строку, которой не существует,
она будет создана:
dataFrame1.loc[50] = [10000, 'Serrano pepper', 'I regret this']
dataFrame1
Выход:
{.ezlazyload}
А если вы хотите удалить строку, вы указываете ее индекс функции
drop()
. Требуется необязательный параметр axis
. axis
принимает
0
/ index
или 1
/ columns
. В зависимости от этого drop()
либо
отбрасывает вызываемую строку, либо столбец, для которого она
вызывается.
Если не указать значение для axis
, соответствующая строка будет
удалена по умолчанию, так как axis
по умолчанию равна 0
dataFrame1.drop(1, inplace=True)
# Same as dataFrame1.drop(1, axis=0)
Выход:
{.ezlazyload}
Вы также можете переименовать строки, которые уже существуют в таблице.
Функция rename()
принимает словарь изменений, которые вы хотите
внести:
dataFrame1.rename({0:"First", 1:"Second"}, inplace=True)
Выход:
{.ezlazyload}
Обратите внимание, что 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
Что дает нам результат:
{.ezlazyload}
Теперь мы можем вызвать drop_duplicates()
:
dataFrame1.drop_duplicates(inplace=True)
dataFrame1
И повторяющиеся строки будут удалены:
{.ezlazyload}
Управление столбцами
Новые столбцы можно добавлять аналогично добавлению строк:
dataFrame1['Color'] = ['Green', 'Bright Red', 'Brown']
dataFrame1
Выход:
{.ezlazyload}
Также, как и строки, столбцы можно удалить, вызвав drop()
, с той лишь
разницей, что вы должны установить axis
необязательных параметров на
1
чтобы Pandas знал, что вы хотите удалить столбец, а не строку:
dataFrame1.drop('Feeling', axis=1, inplace=True)
Выход:
{.ezlazyload}
Когда дело доходит до переименования столбцов, функции rename()
нужно
специально указать, что мы имеем в виду изменить столбцы, установив для
необязательных параметров columns
значение нашего "словаря
изменений":
dataFrame1.rename(columns={"Feeling":"Measure of Pain"}, inplace=True)
Выход:
{.ezlazyload}
Опять же, как и при удалении / переименовании строк, вы можете
установить для необязательного параметра inplace
значение True
если
вы хотите, чтобы исходный DataFrame
вместо функции, возвращающей новый
DataFrame
.
Заключение
В этой статье мы рассмотрели, что такое Pandas DataFrame
, поскольку
они являются ключевым классом фреймворка Pandas, используемого для
хранения данных.
Мы узнали, как создать DataFrame
вручную, используя список и словарь,
после чего мы прочитали данные из файла.
Затем мы манипулировали данными в DataFrame
- используя loc[]
и
iloc[]
, мы находили данные, создавали новые строки и столбцы,
переименовывали существующие и затем отбрасывали их.