Меню Закрити

Огляд бібліотек Python для візуалізації даних

Illustration credit: Vecteezy

Розповідає Aaron Frederick

Існує безліч способів створити графік за допомогою Python, але який із них найкращий? Коли ми робимо візуалізацію, важливо поставити кілька запитань про її мету. Можливо, ви намагаєтеся отримати перше враження від даних? Або плануєте вразити когось на презентації? А може, вам потрібно показати графік колегам, тому достатньо буде звичайної схеми? У цій статті я розгляну низку популярних пакетів візуалізації Python, їхні плюси та мінуси, а також ситуації, коли кожен із них проявляє себе найкраще. Я зосереджу цей огляд на 2D-діаграмах, залишивши місце для 3D-діаграм і панелей на інший раз, хоча багато із цих пакетів цілком добре підтримують обидва варіанти.

Matplotlib, Seaborn, Pandas

Я збираюся об’єднати їх разом із кількох причин, перша з яких полягає в тому, що побудова графіків Seaborn і Pandas відбувається на Matplotlib — коли ви використовуєте Seaborn або df.plot() у Pandas, ви насправді використовуєте код, який було написано з використанням Matplotlib. Тож естетичний результат їх усіх подібний, а способи налаштування діаграм використовують схожий синтаксис.

Коли я думаю про ці засоби візуалізації, то згадую три слова: Exploratory Data Analysis (пошуковий аналіз даних). Ці програмні пакети є чудовими для отримання першого враження про ваші дані, але недостатні, коли справа доходить до презентації. Matplotlib – це низькорівнева бібліотека, яка дає змогу створювати неймовірні налаштування (тому не відмовляйтеся від неї для презентації!). Але існує багато інших інструментів, які значно полегшують створення класної графічної презентації. Matplotlib також має набір стилів,  які імітують інші популярні оформлення — ggplot2 і xkcd. Нижче наведено приклади графіків, зроблених із використанням Matplotlib та його “родичів”.

Працюючи з даними про зарплату в баскетболі, я хотів знайти команди, що мали найвищі середні показники зарплати. Щоб це відобразити, я зробив лінійну діаграму з кольоровим кодом щодо заробітної плати кожної команди, щоб показати, до яких команд гравці повинні звертатися, щоб опинитися там, де добре платять.

import seaborn as sns
import matplotlib.pyplot as plt

color_order = ['xkcd:cerulean', 'xkcd:ocean',
                'xkcd:black','xkcd:royal purple',
                'xkcd:royal purple', 'xkcd:navy blue',
                'xkcd:powder blue', 'xkcd:light maroon', 
                'xkcd:lightish blue','xkcd:navy']

sns.barplot(x=top10.Team,
            y=top10.Salary,
            palette=color_order).set_title('Teams with Highest Median Salary')

plt.ticklabel_format(style='sci', axis='y', scilimits=(0,0))

Наступний графік являє собою Q-Q графік залишків регресійного експерименту. Головна мета цієї візуалізації — показати, наскільки мало рядків потрібно, аби зробити корисну візуалізацію, навіть якщо її естетика не є чимось надзвичайним.

import matplotlib.pyplot as plt
import scipy.stats as stats

#model2 is a regression model
log_resid = model2.predict(X_test)-y_test
stats.probplot(log_resid, dist="norm", plot=plt)
plt.title("Normal Q-Q plot")
plt.show()

Зрештою, Matplotlib та його “родичі” є дуже ефективними, але зазвичай їх недостатньо для створення презентації.

ggplot (2)

Розробники ввели ggplot2 в Python, копіюючи з R все, від естетики до синтаксису. З того матеріалу, що я бачив, він має вигляд і працює як ggplot2, але з додатковою перевагою наявності залежностей від пакета Pandas Python, який нещодавно оголосив застарілими деякі методи, що призвели до неактуальності версії Python.

Що робить ggplot2 (напевно, і ggplot для Python) принципово новим — це те, що вони використовують Grammar of Graphics (граматику графіки) для побудови графіка. Основна ідея полягає в тому, що ви можете створювати свою діаграму, а потім додавати до неї різні функції окремо, тобто назви, осі, точки даних і трендовий рядок додаються окремо з власними естетичними характеристиками. Нижче наведено простий приклад ggplot. Спочатку ми створюємо свій графік за допомогою ggplot, встановлюємо наше оформлення та дані, потім додаємо точки, тему й мітки осей.

#All Salaries
ggplot(data=df, aes(x=season_start, y=salary, colour=team)) +
  geom_point() +
  theme(legend.position="none") +
  labs(title = 'Salary Over Time', x='Year', y='Salary ($)')

Bokeh

Bokeh — чудовий. Концептуально він схожий на ggplot тим, як використовує граматику графіки, щоб структурувати цифри, водночас Bokeh має простий у використанні інтерфейс, що дозволяє робити професійні графіки й панелі. Аби проілюструвати мої слова, далі наведено зразок коду для створення гістограми з набору даних 538 Masculinity Survey (“дослідження маскулінності”).

import pandas as pd
from bokeh.plotting import figure
from bokeh.io import show

# is_masc is a one-hot encoded dataframe of responses to the question:
# "Do you identify as masculine?"

#Dataframe Prep
counts = is_masc.sum()
resps = is_masc.columns

#Bokeh
p2 = figure(title='Do You View Yourself As Masculine?',
          x_axis_label='Response',
          y_axis_label='Count',
          x_range=list(resps))
p2.vbar(x=resps, top=counts, width=0.6, fill_color='red', line_color='black')
show(p2)

#Pandas
counts.plot(kind='bar')

Гістограма відображає відповіді на запитання з цього опитування. Код Bokeh у рядках 9–14 створює елегантну гістограму підрахунку відповідей із доцільним розміром шрифтів, мітками на осі y та форматуванням. Більшість написаного мною коду пішла на маркування осей та заголовка, а також на додавання кольорів і меж. Для створення гарних та презентабельних діаграм я надаю перевагу Bokeh, оскільки там до нас уже зроблено багато естетичної роботи.

Синій графік — це те, що виходить з одного рядка коду під номером 17, наведеного вище. Обидві гістограми мають однакові значення, але слугують різним цілям. Під час дослідження набагато зручніше написати один рядок із pandas, щоб побачити дані, але оформлення Bokeh, безперечно, на голову вище. Будь-яка можливість, яку надає Bokeh, забезпечує кастомізацію в matplotlib, разом із кутом міток осі x, лініями фону, y-tick розповсюдженням, розміром та оформленням шрифту й т. ін. Графік нижче відображає кілька рандомних трендів із використанням більшої кастомізації в легендах та різних типах ліній і кольорів:

Bokeh також є прекрасним інструментом для створення інтерактивних панелей. У цій статті я не хочу заглиблюватися, але є великі публікації, які детально розповідають про застосування та впровадження інформаційних панелей Bokeh.

Plotly

Plotly — надзвичайно потужний інструмент, але налаштування та створення графіків забирають багато часу й не є інтуїтивно зрозумілими. Після того як витратив більшу частину ранку на роботу в Plotly, я пішов на ланч, не маючи майже нічого, щоб показати. Я створив лінійну діаграму без міток осей і “діаграму розсіювання”, що мала рядки, які не міг видалити. Ось найпомітніші мінуси на початку роботи з Plotly:

  • для нього потрібний ключ API і реєстрація, а не просто встановлення пакета;
  • він створює об’єкти даних/макетів, які є унікальними для Plotly, але не інтуїтивними;
  • розмітка діаграми для мене не спрацювала (40 рядків коду — буквально ні для чого!)

Проте за всіх його мінусів існують плюси та обхідні шляхи:

  • можна редагувати графіки на сайті Plotly, а також у середовищі Python;
  • добре підтримуються інтерактивні графіки/панелі;
  • Plotly співпрацює з Mapbox, даючи змогу налаштовувати карти;
  • є чудовий загальний потенціал для неперевершених графіків.

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

#plot 1 - barplot
# **note** - the layout lines do nothing and trip no errors
data = [go.Bar(x=team_ave_df.team,
              y=team_ave_df.turnovers_per_mp)]

layout = go.Layout(
    
    title=go.layout.Title(
        text='Turnovers per Minute by Team',
        xref='paper',
        x=0
    ),
    
    xaxis=go.layout.XAxis(
        title = go.layout.xaxis.Title(
            text='Team',
            font=dict(
                    family='Courier New, monospace',
                    size=18,
                    color='#7f7f7f'
                )
        )
    ),
    
    yaxis=go.layout.YAxis(
        title = go.layout.yaxis.Title(
            text='Average Turnovers/Minute',
            font=dict(
                    family='Courier New, monospace',
                    size=18,
                    color='#7f7f7f'
                )
        )
    ),
    
    autosize=True,
    hovermode='closest')

py.iplot(figure_or_data=data, layout=layout, filename='jupyter-plot', sharing='public', fileopt='overwrite')



#plot 2 - attempt at a scatterplot
data = [go.Scatter(x=player_year.minutes_played,
                  y=player_year.salary,
                  marker=go.scatter.Marker(color='red',
                                          size=3))]

layout = go.Layout(title="test",
                xaxis=dict(title='why'),
                yaxis=dict(title='plotly'))

py.iplot(figure_or_data=data, layout=layout, filename='jupyter-plot2', sharing='public')

У цілому оформлення в результаті має добрий вигляд, але багаторазові спроби фіксації міток копій документації вочевидь не принесли жодних змін. Проте, як я обіцяв вище, ось деякі графіки, які демонструють потенціал Plotly та показують, чому іноді варто витратити більше ніж кілька годин:

Pygal

Pygal — трохи менш відомий пакет, який разом з іншими популярними пакетами використовує фреймворк графічної граматики для побудови своїх зображень. Це відносно простий і чіткий пакет завдяки тому, наскільки простими є графічні об’єкти. Використання Pygal дуже просте:

  1. Активуйте свій графік.
  2. Форматуйте за допомогою атрибутів об’єктів графіка.
  3. Додайте дані до графіка за допомогою figure.add().

Головні складнощі, які я мав із Pygal, були пов’язані з візуалізацією графіків. Мені довелося скористатися їхньою опцією render_to_file, а потім відкрити цей файл у браузері, щоб побачити, що я побудував. У підсумку воно було того варте, оскільки цифри є інтерактивними та мають приємне й конфігурабельне оформлення. Загалом пакет здається вдалим, хоча має деякі заковики в створенні/рендерингу файлів, які обмежують його використання.

Networkx

Networkx є чудовим рішенням для аналізу та візуалізації графіків, хоча він базується візуально на matplotlib. Графіки та мережі не є моєю сферою, але Networkx дає змогу швидкого та простого графічного відображення мереж. Нижче наведено кілька простих графіків, побудованих мною, та код, який почав будувати схему невеликої мережі із Facebook, завантажений зі Стенфордського SNAP .

Нижче наведено код, який я використовував фарбування кожного вузла за його номером (1–10):

options = {
    'node_color' : range(len(G)),
    'node_size' : 300,
    'width' : 1,
    'with_labels' : False,
    'cmap' : plt.cm.coolwarm
}
nx.draw(G, **options)

Ось код, що я написав для візуалізації вищезазначеного графіка Facebook:

import itertools
import networkx as nx
import matplotlib.pyplot as plt

f = open('data/facebook/1684.circles', 'r')
circles = [line.split() for line in f]
f.close()

network = []
for circ in circles:
    cleaned = [int(val) for val in circ[1:]]
    network.append(cleaned)

G = nx.Graph()
for v in network:
    G.add_nodes_from(v)

edges = [itertools.combinations(net,2) for net in network]

for edge_group in edges:
    G.add_edges_from(edge_group)

options = {
    'node_color' : 'lime',
    'node_size' : 3,
    'width' : 1,
    'with_labels' : False,
}
nx.draw(G, **options)

Цей графік досить нещільний, Networkx зображає його, надаючи кожному кластеру максимальне розділення.

Висновок

Існує дуже багато пакетів для візуалізації даних, однак неможливо чітко вирізнити найкращий із них. Сподіваюся, після прочитання цього огляду, ви побачили, як певні види оформлення та коду підходять до різних ситуацій — від автоматизації проектування до презентації.

Ще цікаві статті з програмування.

Якщо ви знайшли помилку, будь ласка, виділіть фрагмент тексту та натисніть Ctrl+Enter.

0

Повідомити про помилку

Текст, який буде надіслано нашим редакторам: