Вступление
Люди редко могут взглянуть на необработанные данные и сразу сделать вывод, ориентированный на данные, например:
Люди в магазинах склонны покупать подгузники и пиво вместе!
Или даже если вы, как специалист по данным, действительно можете читать необработанные данные, скорее всего, ваш инвестор или начальник не смогут.
Чтобы мы могли должным образом анализировать наши данные, нам необходимо представить их осязаемым и всеобъемлющим образом. Именно поэтому мы используем визуализацию данных!
Библиотека pandas
предлагает большой набор инструментов, которые
помогут вам в этом. В этой статье мы шаг за шагом рассмотрим все, что
вам нужно для начала работы с инструментами визуализации pandas
,
включая гистограммы , гистограммы , графики площадей, графики
плотности , матрицы разброса и графики начальной загрузки .
Импорт данных
Во-первых, нам понадобится небольшой набор данных для работы и тестирования.
Я буду использовать набор данных об индийской кухне, поскольку, честно
говоря, индийская еда очень вкусная. Вы можете бесплатно скачать его с
Kaggle.com
. Чтобы импортировать его, мы будем использовать метод read_csv()
который возвращает DataFrame
. Вот небольшой фрагмент кода, который
распечатывает первые пять и последние пять записей в нашем наборе
данных. Давайте попробуем:
import pandas as pd
menu = pd.read_csv('indian_food.csv')
print(menu)
Запуск этого кода приведет к выводу:
name state region ... course
0 Balu shahi West Bengal East ... dessert
1 Boondi Rajasthan West ... dessert
2 Gajar ka halwa Punjab North ... dessert
3 Ghevar Rajasthan West ... dessert
4 Gulab jamun West Bengal East ... dessert
.. ... ... ... ... ...
250 Til Pitha Assam North East ... dessert
251 Bebinca Goa West ... dessert
252 Shufta Jammu & Kashmir North ... dessert
253 Mawa Bati Madhya Pradesh Central ... dessert
254 Pinaca Goa West ... dessert
Если вы хотите загрузить данные из другого формата файла, pandas
предлагает аналогичные методы чтения, такие как read_json()
. Вид
немного урезан из-за длинной формы переменной ingredients
Чтобы извлечь только несколько выбранных столбцов, мы можем разделить набор данных с помощью квадратных скобок и перечислить имена столбцов, на которых мы хотели бы сосредоточиться:
import pandas as pd
menu = pd.read_csv('indian_food.csv')
recepies = menu[['name', 'ingredients']]
print(recepies)
Это дает:
name ingredients
0 Balu shahi Maida flour, yogurt, oil, sugar
1 Boondi Gram flour, ghee, sugar
2 Gajar ka halwa Carrots, milk, sugar, ghee, cashews, raisins
3 Ghevar Flour, ghee, kewra, milk, clarified butter, su...
4 Gulab jamun Milk powder, plain flour, baking powder, ghee,...
.. ... ...
250 Til Pitha Glutinous rice, black sesame seeds, gur
251 Bebinca Coconut milk, egg yolks, clarified butter, all...
252 Shufta Cottage cheese, dry dates, dried rose petals, ...
253 Mawa Bati Milk powder, dry fruits, arrowroot powder, all...
254 Pinaca Brown rice, fennel seeds, grated coconut, blac...
[255 rows x 2 columns]
Построение гистограмм с помощью панд
Классическую гистограмму легко читать, и с нее можно начать - давайте визуализируем, сколько времени уходит на приготовление каждого блюда.
Pandas полагается на движок Matplotlib для отображения сгенерированных
графиков. Поэтому нам придется импортировать модуль PyPlot из Matplotlib
для вызова plt.show()
после создания графиков.
Во-первых, давайте импортируем наши данные. В нашем наборе данных много блюд - 255, если быть точным. Это не совсем вписывается в одну цифру, оставаясь читаемым.
Мы воспользуемся head()
для извлечения первых 10 блюд и извлечем
переменные, относящиеся к нашему графику. А именно, мы хотим извлечь
name
и время cook_time
для каждого блюда в новый DataFrame с именем
name_and_time
и усечь его до первых 10 блюд:
import pandas as pd
import matplotlib.pyplot as plt
menu = pd.read_csv('indian_food.csv')
name_and_time = menu[['name','cook_time']].head(10)
Теперь мы воспользуемся bar()
для построения наших данных:
DataFrame.plot.bar(x=None, y=None, **kwargs)
- Параметры
x
иy
соответствуют осям X и Y kwargs
соответствует дополнительным аргументам ключевого слова, которые задокументированы вDataFrame.plot()
.
Для дальнейшей настройки графика можно передать множество дополнительных
параметров, таких как rot
для поворота метки, legend
для добавления
легенды, style
и т. Д.
Многие из этих аргументов имеют значения по умолчанию, большинство из
которых отключены. Поскольку аргумент rot
90
, наши метки будут
повернуты на 90 градусов. Давайте изменим это значение на 30 при
построении графика:
name_and_time.plot.bar(x='name',y='cook_time', rot=30)
И, наконец, мы вызовем метод show()
из экземпляра PyPlot для
отображения нашего графика:
plt.show()
Это выведет нашу желаемую гистограмму:
{.ezlazyload}
Построение нескольких столбцов на оси X гистограммы в Pandas
Часто нам может понадобиться сравнить две переменные на гистограмме,
например, cook_time
и prep_time
. Это обе переменные,
соответствующие каждому блюду, и их можно напрямую сравнивать.
Давайте изменим name_and_time
name_and_time, чтобы он также включал
prep_time
:
name_and_time = menu[['name','prep_time','cook_time']].head(10)
name_and_time.plot.bar(x='name', rot=30)
Pandas автоматически предположил, что два числовых значения рядом с
name
привязаны к нему, поэтому достаточно просто определить ось X. При
работе с другими DataFrames это может быть не так.
Если вам нужно явно определить, какие другие переменные должны отображаться, вы можете просто передать список:
name_and_time.plot.bar(x='name', y=['prep_time','cook_time'], rot=30)
Выполнение любого из этих двух кодов даст:
{.ezlazyload}
Это интересно. Кажется, что еда, которую готовят быстрее, требует больше
времени, и наоборот. Хотя это действительно исходит из довольно
ограниченного набора данных, и это предположение может быть неверным для
других подмножеств.
Построение гистограмм с накоплением с помощью панд
Давайте посмотрим, на приготовление какого блюда уходит больше всего времени. Поскольку мы хотим учитывать как время подготовки, так и время приготовления, мы сложим их друг на друга.
Для этого мы установим для параметра stacked
True
:
name_and_time.plot.bar(x='name', stacked=True)
{.ezlazyload}
Теперь мы можем легко увидеть, какие блюда готовятся дольше всего, учитывая время приготовления и время приготовления.
Настройка гистограмм в пандах
Если мы хотим, чтобы графики выглядели немного лучше, мы можем передать
некоторые дополнительные аргументы bar()
, например:
color
- который определяет цвет для каждого изDataFrame
. Это может быть строка, например,'orange'
,rgb
или rgb-code, например#faa005
.title
- строка или список, обозначающий заголовок сюжета.grid
- логическое значение, указывающее, видны ли линии сетки.figsize
- Кортеж, указывающий размер графика в дюймах.legend
- логическое значение, которое указывает, отображается ли легенда.
Если нам нужна горизонтальная гистограмма, мы можем использовать метод
barh()
который принимает те же аргументы.
Например, давайте построим горизонтальную оранжево-зеленую гистограмму с
заголовком "Dishes"
с сеткой размером 5 на 6 дюймов и легендой:
import pandas as pd
import matplotlib.pyplot as plt
menu = pd.read_csv('indian_food.csv')
name_and_time = menu[['name','cook_time','prep_time']].head()
name_and_time.plot.barh(x='name',color =['orange','green'], title = "Dishes", grid = True, figsize=(5,6), legend = True)
plt.show()
{.ezlazyload}
Построение гистограмм с помощью панд
Гистограммы полезны для отображения распределения данных. Глядя на один рецепт, мы понятия не имеем, близко ли время приготовления к среднему времени приготовления или это занимает очень много времени. В определенной степени нам в этом могут помочь средства, но они могут вводить в заблуждение или приводить к огромным ошибкам.
Чтобы получить представление о распределении, которое дает нам много информации о времени приготовления, нам нужно построить график гистограммы.
С помощью Pandas мы можем вызвать hist()
в DataFrame, чтобы
сгенерировать его гистограмму:
DataFrame.hist(column=None, by=None, grid=True, xlabelsize=None, xrot=None, ylabelsize=None, yrot=None, ax=None, sharex=False, sharey=False, fcigsize=None, layout=None, bins=10, backend=None, legend=False,**kwargs)
Параметр bins
указывает количество используемых бинов.
Большая часть работы с любым набором данных - это очистка и
предварительная обработка данных. В нашем случае для некоторых продуктов
не указано правильное время приготовления и приготовления (вместо этого
указано значение -1
Давайте отфильтруем их из нашего меню, прежде чем визуализировать гистограмму. Это самый простой тип предварительной обработки данных. В некоторых случаях вам может потребоваться изменить типы данных (например, строки в денежном формате на числа с плавающей запятой) или даже создать новые точки данных на основе какой-либо другой переменной.
Отфильтруем недопустимые значения и построим гистограмму с 50 ячейками по оси X:
import pandas as pd
import matplotlib.pyplot as plt
menu = pd.read_csv('indian_food.csv')
menu = menu[menu.cook_time != -1] # Filtering
cook_time = menu['cook_time']
cook_time.plot.hist(bins = 50)
plt.legend()
plt.show()
Это приводит к:
{.ezlazyload}
По оси Y мы можем видеть частоту блюд, а по оси X - сколько времени они готовятся.
Чем выше полоса, тем выше частота. Согласно этой гистограмме,
приготовление большинства блюд занимает от 0..80
до 80 минут.
Наибольшее их количество находится на действительно высоком баре, хотя
мы не можем точно определить, какое это число, потому что частота наших
тиков низкая (один каждые 100 минут).
А пока давайте попробуем изменить количество интервалов, чтобы увидеть, как это повлияет на нашу гистограмму. После этого мы можем изменить частоту тиков.
Выделение данных с помощью размеров корзины
Давайте попробуем вместо этого построить эту гистограмму с 10
ячейками:
import pandas as pd
import matplotlib.pyplot as plt
menu = pd.read_csv('indian_food.csv')
menu = menu[menu.cook_time != -1] # Filtering
cook_time = menu['cook_time']
cook_time.plot.hist(bins = 10)
plt.legend()
plt.show()
{.ezlazyload}
Теперь у нас есть 10 интервалов по всей оси X. Обратите внимание, что только 3 ячейки имеют некоторую частоту данных, а остальные пусты.
Теперь давайте, возможно, увеличим количество ящиков:
import pandas as pd
import matplotlib.pyplot as plt
menu = pd.read_csv('indian_food.csv')
menu = menu[menu.cook_time != -1] # Filtering
cook_time = menu['cook_time']
cook_time.plot.hist(bins = 100)
plt.legend()
plt.show()
{.ezlazyload}
Теперь контейнеры неудобно расположены далеко друг от друга, и из-за этого мы снова потеряли некоторую информацию. Вы всегда захотите поэкспериментировать с размерами бункеров и настроить их, пока данные, которые вы хотите исследовать, не будут отображаться красиво.
Настройки по умолчанию (номер ячейки по умолчанию - 10) в этом случае привели бы к нечетному номеру ячейки.
Изменить частоту тиков для гистограммы панд
Поскольку мы используем Matplotlib в качестве движка для отображения этих графиков, мы также можем использовать любые методы настройки Matplotlib.
Так как наши отметки по оси X немного редки, мы 0
и cook_time.max()
, который возвращает запись с наибольшим числом.
Кроме того, поскольку на нашем графике будет много меток, мы повернем их на 45 градусов, чтобы убедиться, что они подходят друг другу:
import pandas as pd
import matplotlib.pyplot as plt
import numpy as np
# Clean data and extract what we're looking for
menu = pd.read_csv('indian_food.csv')
menu = menu[menu.cook_time != -1] # Filtering
cook_time = menu['cook_time']
# Construct histogram plot with 50 bins
cook_time.plot.hist(bins=50)
# Modify X-Axis ticks
plt.xticks(np.arange(0, cook_time.max(), 20))
plt.xticks(rotation = 45)
plt.legend()
plt.show()
Это приводит к:
{.ezlazyload}
Построение нескольких гистограмм
Теперь добавим время приготовления в смесь. Чтобы добавить эту гистограмму, мы построим ее как отдельную настройку гистограммы с непрозрачностью 60%.
У них будут общие оси Y и X, поэтому они будут перекрываться. Не сделав их немного прозрачными, мы могли бы не увидеть гистограмму под второй гистограммой, которую строим:
import pandas as pd
import matplotlib.pyplot as plt
import numpy as np
# Filtering and cleaning
menu = pd.read_csv('indian_food.csv')
menu = menu[(menu.cook_time!=-1) & (menu.prep_time!=-1)]
# Extracting relevant data
cook_time = menu['cook_time']
prep_time = menu['prep_time']
# Alpha indicates the opacity from 0..1
prep_time.plot.hist(alpha = 0.6 , bins = 50)
cook_time.plot.hist(alpha = 0.6, bins = 50)
plt.xticks(np.arange(0, cook_time.max(), 20))
plt.xticks(rotation = 45)
plt.legend()
plt.show()
Это приводит к:
{.ezlazyload}
Мы можем сделать вывод, что большинство блюд можно приготовить менее чем за час или примерно за час. Однако есть некоторые, на приготовление которых уходит пара дней с 10-часовым временем приготовления и длительным временем приготовления.
Настройка графиков гистограмм
Чтобы настроить гистограммы, мы можем использовать те же аргументы ключевых слов, которые мы использовали для столбчатой диаграммы.
Например, сделаем зеленую и красную гистограмму с заголовком, сеткой, легендой - размером 7x7 дюймов:
import pandas as pd
import matplotlib.pyplot as plt
import numpy as np
menu = pd.read_csv('indian_food.csv')
menu = menu[(menu.cook_time!=-1) & (menu.prep_time!=-1)] #filltering
cook_time = menu['cook_time']
prep_time = menu['prep_time']
prep_time.plot.hist(alpha = 0.6 , color = 'green', title = 'Cooking time', grid = True, bins = 50)
cook_time.plot.hist(alpha = 0.6, color = 'red', figsize = (7,7), grid = True, bins = 50)
plt.xticks(np.arange(0, cook_time.max(), 20))
plt.xticks(rotation = 45)
plt.legend()
plt.show()
А вот наша гистограмма цвета Рождества:
{.ezlazyload}
Построение участков с пандами
Графики площадей удобны при рассмотрении корреляции двух параметров. Например, исходя из графиков гистограмм, было бы правильно склоняться к идее, что еда, которая требует больше времени на приготовление, требует меньше времени на приготовление.
Чтобы проверить это, мы построим эту взаимосвязь с помощью функции
area()
:
DataFrame.plot.area(x=None, y=None, **kwargs)
Давайте использовать среднее время приготовления, сгруппированное по времени приготовления, чтобы упростить этот график:
time = menu.groupby('prep_time').mean()
Это приводит к новому DataFrame:
prep_time
5 20.937500
10 40.918367
12 40.000000
15 36.909091
20 36.500000
...
495 40.000000
500 120.000000
Теперь мы построим график площади с полученным DataFrame time
import pandas as pd
import matplotlib.pyplot as plt
menu = pd.read_csv('indian_food.csv')
menu = menu[(menu.cook_time!=-1) & (menu.prep_time!=-1)]
# Simplifying the graph
time = menu.groupby('prep_time').mean()
time.plot.area()
plt.legend()
plt.show()
{.ezlazyload}
Здесь наше представление об изначальной корреляции между временем приготовления и временем приготовления было разрушено. Несмотря на то, что другие типы графиков могут привести нас к некоторым выводам - существует своего рода корреляция, подразумевающая, что с более высоким временем приготовления у нас также будет более высокое время приготовления. Это противоположно тому, что мы предполагали.
Это отличная причина не придерживаться только одного типа графика, а лучше изучить свой набор данных с помощью нескольких подходов.
Построение участков с накоплением
Диаграммы с областями имеют очень похожий набор аргументов ключевых слов, как гистограммы и гистограммы. Одно из заметных исключений:
stacked
- логическое значение, которое указывает, будут ли два или более графика складываться или нет
Давайте наметим время приготовления и подготовки так, чтобы они были сложены, розовые и фиолетовые, с сеткой размером 8x9 дюймов с легендой:
import pandas as pd
import matplotlib.pyplot as plt
menu = pd.read_csv('indian_food.csv')
menu = menu[(menu.cook_time!=-1) & (menu.prep_time!=-1)]
menu.plot.area()
plt.legend()
plt.show()
{.ezlazyload}
Построение круговых диаграмм с помощью панд
Круговые диаграммы полезны, когда у нас есть небольшое количество категориальных значений, которые нам нужно сравнить. Они очень ясны и по делу, однако будьте осторожны. Читаемость круговых диаграмм сильно ухудшается при малейшем увеличении количества категориальных значений.
Для построения круговых диаграмм мы будем использовать pie()
которая
имеет следующий синтаксис:
DataFrame.plot.pie(**kwargs)
Нанесение вкусовых профилей:
import pandas as pd
import matplotlib.pyplot as plt
menu = pd.read_csv('indian_food.csv')
flavors = menu[menu.flavor_profile != '-1']
flavors['flavor_profile'].value_counts().plot.pie()
plt.legend()
plt.show()
Это приводит к:
{.ezlazyload}
Безусловно, большинство блюд острые и сладкие.
Настройка круговых диаграмм
Чтобы сделать нашу круговую диаграмму более привлекательной, мы можем настроить ее с помощью тех же аргументов ключевого слова, которые мы использовали во всех предыдущих альтернативах диаграммы, с некоторыми нововведениями:
shadow
- логическое значение, которое указывает, есть ли у секторов круговой диаграммы теньstartangle
- Начальный угол круговой диаграммы
Чтобы показать, как это работает, нарисуем регионы, из которых
происходят блюда. Мы будем использовать head()
чтобы взять только
первые 10
, чтобы не было слишком много фрагментов.
Давайте сделаем пирог розовым, с заголовком «Состояния», добавим тень и
легенду и начнем под углом 15
:
import pandas as pd
import matplotlib.pyplot as plt
menu = pd.read_csv('indian_food.csv')
states = (menu[menu.state != '-1'])['state'].value_counts().head(10)
# Colors to circle through
colors = ['lightpink','pink','fuchsia','mistyrose','hotpink','deeppink','magenta']
states.plot.pie(colors = colors, shadow = True, startangle = 15, title = "States")
plt.show()
{.ezlazyload}
Построение графиков плотности с помощью панд
Если у вас есть опыт работы со статистикой, вы, вероятно, видели график плотности. Графики плотности - это визуальное представление плотности вероятности в диапазоне значений.
Гистограмма - это график плотности, который объединяет точки данных в категории. Второй по популярности график плотности - график KDE (оценка плотности ядра) - проще говоря, он похож на очень гладкую гистограмму с бесконечным количеством интервалов.
Чтобы построить его, мы воспользуемся функцией kde()
DataFrame.plot.kde(bw_method=None, ind=None, **kwargs)
Например, нарисуем время приготовления:
import pandas as pd
import matplotlib.pyplot as plt
import scipy
menu = pd.read_csv('indian_food.csv')
time = (menu[menu.cook_time != -1])['cook_time']
time.value_counts().plot.kde()
plt.show()
Это распределение выглядит так:
{.ezlazyload}
В разделе « Гистограмма » мы изо всех сил пытались собрать всю необходимую информацию и данные с помощью бинов, потому что каждый раз, когда мы обобщаем и объединяем данные вместе, мы теряем некоторую точность.
С графиками KDE мы можем эффективно использовать бесконечное количество бинов. Таким образом никакие данные не усекаются и не теряются.
Построение матрицы рассеяния (парный график) в пандах
Немного более сложный способ интерпретации данных - использование матриц рассеяния . Это способ учесть взаимосвязь каждой пары параметров. Если вы работали с другими библиотеками, этот тип графика может быть вам знаком как парный .
Чтобы построить матрицу разброса, нам нужно импортировать
scatter_matrix()
из модуля pandas.plotting
Синтаксис функции scatter_matrix()
:
pandas.plotting.scatter_matrix(frame, alpha=0.5, figsize=None, ax=None, grid=False, diagonal='hist', marker='.', density_kwds=None, hist_kwds=None, range_padding=0.05, **kwargs)
Поскольку мы строим попарные отношения для нескольких классов в сетке - все диагональные линии в сетке будут устаревшими, поскольку он сравнивает запись с самим собой. Поскольку это будет мертвое пространство, диагонали заменяются графиком одномерного распределения для этого класса.
diagonal
параметр может иметь значение 'kde'
или 'hist
» либо для
оценки плотности ядра, либо для графиков гистограммы.
Создадим график матрицы рассеяния:
import pandas as pd
import matplotlib.pyplot as plt
import scipy
from pandas.plotting import scatter_matrix
menu = pd.read_csv('indian_food.csv')
scatter_matrix(menu,diagonal='kde')
plt.show()
Сюжет должен выглядеть так:
{.ezlazyload}
Построение графика начальной загрузки в Pandas
Pandas также предлагает Bootstrap Plot для ваших нужд построения графиков. График начальной загрузки - это график, который вычисляет несколько различных статистических данных с разными размерами подвыборки. Затем на основе накопленных данных по статистике он генерирует распределение самих статистических данных.
Использовать его так же просто, как импортировать метод
bootstrap_plot()
из модуля pandas.plotting
Синтаксис
bootstrap_plot()
pandas.plotting.bootstrap_plot(series, fig=None, size=50, samples=500, **kwds)
И, наконец, построим Bootstrap Plot:
import pandas as pd
import matplotlib.pyplot as plt
import scipy
from pandas.plotting import bootstrap_plot
menu = pd.read_csv('indian_food.csv')
bootstrap_plot(menu['cook_time'])
plt.show()
Сюжет начальной загрузки будет выглядеть примерно так:
{.ezlazyload}
Заключение
В этом руководстве мы рассмотрели введение в визуализацию данных в Python с помощью Pandas . Мы рассмотрели основные графики, такие как круговые диаграммы, гистограммы, перешли на графики плотности, такие как гистограммы и графики KDE.
Наконец, мы рассмотрели матрицы разброса и графики начальной загрузки.
Если вас интересует визуализация данных и вы не знаете, с чего начать, обязательно ознакомьтесь с нашей книгой о визуализации данных в Python{.ebook-link} .
Книга «Визуализация данных в Python» , книга для начинающих и средних разработчиков Python, проведет вас через простые операции с данными с помощью Pandas, расскажет о базовых библиотеках построения графиков, таких как Matplotlib и Seaborn, и покажет, как воспользоваться преимуществами декларативных и экспериментальных библиотек, таких как Altair.
::: {style=“border: 1px solid #ebebeb;padding: 15px;margin-bottom: 30px;”} {.ebook-link}
Визуализация данных в Python
::: {.row} ::: {.col-md-4 .col-xs-12} {.ezlazyload .img-responsive .center-block} :::
::: {.col-md-8 .col-xs-12 .my-auto} Поймите свои данные лучше с помощью визуализаций! На 340 страницах вы узнаете все тонкости визуализации данных в Python с помощью популярных библиотек, таких как Matplotlib, Seaborn, Bokeh и других. ::: ::: :::