Вступление

Чтобы лучше визуализировать свои данные, вы можете собрать все в одном месте, создав панель управления. Plotly Express - это инструмент, который позволит вам легко создавать потрясающие интерактивные графики, а с Plotly Dash вы можете использовать их для создания информационной панели.

В этой статье я покажу вам, как создать два графика и собрать их вместе на простой панели инструментов. В качестве примера мы будем использовать данные о COVID-19 по всему миру.

Метод

Первый график, который мы создадим, - это диаграмма рассеяния на карте мира, показывающая эволюцию случаев заболевания в течение недель 2020 года. Данные о COVID-19 во всем мире взяты из Нашего мира в наборе данных COVID-19. Также нам потребуются координаты каждой страны, которые я взял из этого набора данных на Kaggle.

import pandas as pd
import plotly.express as px
covid = pd.read_csv('full_data.csv')
covid = covid[['date', 'location', 'total_cases', 'total_deaths']]
countries_geo = pd.read_csv('countries.csv')
countries_geo = countries_geo[['latitude', 'longitude', 'name']]
countries_geo.columns = ['latitude', 'longitude', 'location']

Теперь, когда мы импортировали оба набора данных, давайте объединим их. После слияния я также преобразовал столбец даты в формат datetime и заполнил нулевые значения 0.

countries = pd.merge(covid, countries_geo, how='inner', on='location')
countries['date'] = pd.to_datetime(countries['date'])
countries = countries[countries.date.dt.year == 2020].copy()
countries.fillna(0, inplace=True)

Последнее, что нам нужно сделать с нашими данными, - это систематизировать их по неделям. Я добился этого, выбрав только строки с данными по воскресеньям, а затем с помощью метода isocalendar создал новый столбец с соответствующим номером недели.

countries_week = countries[countries.date.dt.weekday == 6].copy()
countries_week['week'] = countries_week['date'].dt.isocalendar()['week']

Теперь мы можем создать наш первый график, используя функцию scatter_geo в Plotly.

fig_map = px.scatter_geo(
    countries_week,
    lat = 'latitude',
    lon = 'longitude',
    size = 'total_cases',
    hover_name = 'location',
    hover_data = ["total_cases", "total_deaths"],
    title = "COVID-19 Evolution in 2020",
    animation_frame = "week",
    color="total_cases",
    labels={
        'total_cases': 'Cases',
        'total_deaths': 'Deaths',
        'week': 'Week',
        'latitude': 'Latitude',
        'longitude': 'Longitude'
    },
    projection = 'natural earth'
)
fig_map.show()

Результатом является карта мира с точками, размер которых пропорционален общему количеству случаев в каждой стране. Цвет также меняется в соответствии с этим числом, и вы можете просмотреть исторические данные, используя слайд внизу. Если вы наведете курсор на точку, появится дополнительная информация.

Следующий график, который мы создадим, представляет собой линейный график, показывающий эволюцию случаев в текущих 10 странах с наибольшим количеством подтвержденных случаев. Для этого нам нужно знать, что это за страны. Поэтому мы выберем строки за последнюю неделю, отсортируем их по total_cases и извлечем только первые 10 в виде списка.

top10 = countries_week[countries_week.week == countries_week.week.max()].sort_values('total_cases', ascending=False).iloc[:10, 1].to_list()

Теперь мы можем создать график, сравнивающий развитие COVID-19 в этих странах.

fig_line = px.line(
    countries_week[countries_week.location.isin(top10)],
    x="week",
    y="total_cases",
    log_y = False,
    color='location',
    hover_name = 'location',
    hover_data = ["total_cases", "total_deaths"],
    title = "COVID-19 Evolution in 2020 (Top 10 Countries)",
    labels= {
        'total_cases': 'Cases',
        'total_deaths': 'Deaths',
        'week': 'Week',
        'latitude': 'Latitude',
        'longitude': 'Longitude',
        'location': 'Country'
    }
)
fig_line.show()

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

Последнее, что мы сделаем, - это создадим веб-страницу панели инструментов с этими двумя графиками, используя Plotly Dash и Ngrok. Plotly Dash - это платформа для создания веб-приложений для машинного обучения и обработки данных. Ngrok - это инструмент, который предоставляет нам общедоступный URL-адрес нашего локального хоста (он понадобится вам, если вы запускаете свой код с помощью Google Colab, как я).

Во-первых, нам нужно установить Plotly Dash на нашу машину Colab.

!pip install dash
!pip install dash-html-components
!pip install dash-core-components
!pip install dash-table

Теперь мы можем импортировать все, что нам нужно.

import os.path
import sys, json
import requests
import subprocess
import numpy as np
import pandas as pd
import plotly.express as px
from requests.exceptions import RequestException
from requests.adapters import HTTPAdapter
from requests.packages.urllib3.util.retry import Retry
from collections import namedtuple

Вы можете определить следующую функцию для загрузки Ngrok.

def download_ngrok():
    if not os.path.isfile('ngrok'):
        !wget https://bin.equinox.io/c/4VmDzA7iaHb/ngrok-stable-linux-amd64.zip
        !unzip -o ngrok-stable-linux-amd64.zip
    pass

Мы также будем использовать функцию для настройки туннелирования Ngrok.

Response = namedtuple('Response', ['url', 'error'])
def get_tunnel():
    try:
        Tunnel = subprocess.Popen(['./ngrok','http','8050'])
session = requests.Session()
        retry = Retry(connect=3, backoff_factor=0.5)
        adapter = HTTPAdapter(max_retries=retry)
        session.mount('http://', adapter)
res = session.get('http://localhost:4040/api/tunnels')
        res.raise_for_status()
tunnel_str = res.text
        tunnel_cfg = json.loads(tunnel_str)
        tunnel_url = tunnel_cfg['tunnels'][0]['public_url']
return Response(url=tunnel_url, error=None)
    except RequestException as e:
        return Response(url=None, error=str(e))

Последний шаг - создать скрипт, который будет создавать и обслуживать информационную панель. Мы будем использовать %%writefile поверх кода, чтобы он был записан на диск.

%%writefile my_dash_app.py
import dash
import dash_core_components as dcc
import dash_html_components as html
from dash.dependencies import Input, Output
import pandas as pd
import plotly.express as px
external_stylesheets = ['https://codepen.io/chriddyp/pen/bWLwgP.css']
app = dash.Dash(__name__, external_stylesheets=external_stylesheets)
# THE PREVIOUS CODE TO CREATE THE GRAPHS COMES HERE
# You can edit this layout to include more graphs
app.layout = html.Div(children=[
    html.Div([
        html.H1(children='COVID-19 Evolution in 2020'),
dcc.Graph(
            id='graph1',
            figure=fig_map
        ),  
    ]),
    html.Div([
        dcc.Graph(
            id='graph2',
            figure=fig_line
        ),  
    ]),
])
if __name__ == '__main__':
    app.run_server(debug=True, use_reloader=True)

Теперь запустите функцию загрузки Ngrok, если вы еще этого не сделали, и запустите сервер с помощью следующих команд.

tunnel = get_tunnel()
print(tunnel)
!python my_dash_app.py

Вы должны увидеть что-то подобное.

Нажмите на первую ссылку, чтобы открыть панель управления, и вот она!

Обратите внимание, что ссылка будет работать только до тех пор, пока сервер будет работать. Вы можете использовать другие услуги хостинга для постоянной ссылки, например Heroku.

использованная литература

Исходные данные о коронавирусе
https://ourworldindata.org/coronavirus-source-data

Географические координаты стран
https://www.kaggle.com/eidanch/counties-geographic-coordinates

Блокнот IPython
https://github.com/edusrmt/one-figure-projects

Сюжетный экспресс
https://plotly.com/python/plotly-express/