Artigo original: How to Embed Interactive Python Visualizations on Your Website with Python and Matplotlib

Em um tutorial anterior do freeCodeCamp, expliquei como criar visualizações de dados com atualizações automáticas em Python (texto em inglês).

Alguns leitores perguntaram se havia algum modo de tornar as visualizações interativas. Felizmente, uma solução fácil já está disponível!

Neste tutorial, vou ensinar como você pode criar visualizações interativas de dados em Python. Essas visualizações são excelentes candidatas para incorporação em seu blog ou site.

A visualização de dados específica com a qual trabalharemos

Em vez de construir uma visualização de dados inteira do zero neste artigo, trabalharemos com a visualização que criamos em meu último tutorial.

A visualização usa pandas, matplotlib e Python para apresentar vários pontos de dados dos 5 maiores bancos de capital aberto dos Estados Unidos.

Aqui está uma imagem estática da visualização que criamos:

image-55

O código real para a visualização está incluído abaixo. Abordamos isso no último tutorial, mas observe que você precisará gerar sua própria chave de API IEX Cloud e incluí-la na variável IEX_API_Key para que o script funcione.

############################
#Importação das dependências
############################

import pandas as pd
import matplotlib.pyplot as plt

###############################
#Importação e limpeza dos dados
###############################

IEX_API_Key = ''

tickers = [
            'JPM',
            'BAC',
            'C',
            'WFC',
            'GS',
            ]

#Crie uma string vazia chamada `ticker_string`, a qual adicionaremos tickers e vírgulas
ticker_string = ''

#Percorra cada elemento de `tickers` e adicione-os com uma vírgula a ticker_string
for ticker in tickers:
    ticker_string += ticker
    ticker_string += ','
    
#Remova a última vírgula de `ticker_string`
ticker_string = ticker_string[:-1]

#Crie as strings endpoint e years
endpoints = 'chart'
years = '5'

#Faça a interpolação das strings endpoint em HTTP_request string
HTTP_request = f'https://cloud.iexapis.com/stable/stock/market/batch?symbols={ticker_string}&types={endpoints}&range={years}y&cache=true&token={IEX_API_Key}'

#Envie a solicitação HTTP à API IEX Cloud e armazene a resposta em um DataFrame do pandas
bank_data = pd.read_json(HTTP_request)

#Crie uma lista vazia, onde adicionaremos uma série do pandas de dados de preços de ações
series_list = []

#Percorra cada um dos tickers e mostre uma série do pandas com seus preços ao encerramento da bolsa nos últimos 5 anos
for ticker in tickers:
    series_list.append(pd.DataFrame(bank_data[ticker]['chart'])['close'])

#Adicione a coluna dates (datas)
series_list.append(pd.DataFrame(bank_data['JPM']['chart'])['date'])

#Copie a lista 'tickers' que aparece anteriormente no script e adicione um novo elemento chamado 'Date'. 
#Esses elementos serão os nomes das colunas de nosso DataFrame do pandas posteriormente.
column_names = tickers.copy()
column_names.append('Date')

#Concatene as séries do pandas Series em um único DataFrame
bank_data = pd.concat(series_list, axis=1)

#Nomeie as colunas do DataFrame e defina a coluna 'Date' como o índice
bank_data.columns = column_names
bank_data.set_index('Date', inplace = True)

########################
#Crie a imagem do Python
########################

#Defina o tamanho do canvas do matplotlib
fig = plt.figure(figsize = (18,8))

################################################
################################################
#Crie subgráficos no Python
################################################
################################################

########################
#Subgráfico 1
########################
plt.subplot(2,2,1)

#Gere o diagrama de caixas (boxplot)
plt.boxplot(bank_data.transpose())

#Adicione títulos ao gráfico e aos eixos
plt.title('Boxplot of Bank Stock Prices (5Y Lookback)')
plt.xlabel('Bank')
plt.ylabel('Stock Prices')

#Adicione os rótulos a cada diagrama de caixas individual no canvas
ticks = range(1, len(bank_data.columns)+1)
labels = list(bank_data.columns)
plt.xticks(ticks,labels)

########################
#Subgráfico 2
########################
plt.subplot(2,2,2)

#Crie os dados do eixo x
dates = bank_data.index.to_series()
dates = [pd.to_datetime(d) for d in dates]

#Crie os dados do eixo y
WFC_stock_prices =  bank_data['WFC']

#Gere o gráfico de dispersão (scatterplot)
plt.scatter(dates, WFC_stock_prices)

#Adicione títulos ao gráfico e aos eixos
plt.title("Wells Fargo Stock Price (5Y Lookback)")
plt.ylabel("Stock Price")
plt.xlabel("Date")

########################
#Subgráfico 3
########################
plt.subplot(2,2,3)

#Crie os dados do eixo x
dates = bank_data.index.to_series()
dates = [pd.to_datetime(d) for d in dates]

#Crie os dados do eixo y
BAC_stock_prices =  bank_data['BAC']

#Gere o gráfico de dispersão (scatterplot)
plt.scatter(dates, BAC_stock_prices)

#Adicione títulos ao gráfico e aos eixos
plt.title("Bank of America Stock Price (5Y Lookback)")
plt.ylabel("Stock Price")
plt.xlabel("Date")

########################
#Subgráfico 4
########################
plt.subplot(2,2,4)

#Gere o histograma
plt.hist(bank_data.transpose(), bins = 50)

#Adicione uma legenda ao histograma
plt.legend(bank_data.columns,fontsize=10)

#Adicione títulos ao gráfico e aos eixos
plt.title("A Histogram of Daily Closing Stock Prices for the 5 Largest Banks in the US (5Y Lookback)")
plt.ylabel("Observations")
plt.xlabel("Stock Prices")

plt.tight_layout()

################################################
#Salve a imagem em sua máquina local
################################################

plt.savefig('bank_data.png')

Agora que entendemos a visualização específica com a qual trabalharemos, vamos falar sobre o que significa uma visualização ser interativa.

O que significa uma visualização ser interativa?

Existem dois tipos de visualizações de dados que são úteis para embutir em seu site.

O primeiro tipo é uma visualização estática. Esta é basicamente uma imagem - pense em arquivos .png ou .jpg.

O segundo tipo é uma visualização dinâmica. Essas visualizações mudam em resposta ao comportamento do usuário, geralmente via panorâmica ou zoom. As visualizações dinâmicas não são armazenadas em arquivos .png ou .jpg, mas geralmente em tags svg ou iframe.

Este tutorial é sobre criação de visualizações dinâmicas de dados. Especificamente, a visualização que queremos criar terá as seguintes características:

  1. Você clicará em um botão no canto inferior esquerdo para ativar o modo dinâmico.
  2. Depois que o modo dinâmico estiver ativado, você poderá ampliar e deslocar a visualização com o mouse.
  3. Você também pode cortar e dar zoom em uma seção específica da visualização.

Na próxima seção deste tutorial, você aprenderá como instalar e importar a biblioteca mpld3, que é a dependência do Python que usaremos para criar nossos gráficos interativos.

Como importar a biblioteca mpld3

Para usar a biblioteca mpld3 em nossa aplicação do Python, há duas etapas que precisamos concluir primeiro:

  1. Instalar a biblioteca mpld3 na máquina em que estamos trabalhando.
  2. Importar a biblioteca mpld3 em nosso script do Python.

Primeiro, vamos instalar o mpld3 em nossa máquina local.

A maneira mais fácil de fazer isso é usando o gerenciador de pacotes pip para Python3. Se você já tem o pip instalado em sua máquina, você pode fazer isso executando a seguinte declaração na sua linha de comando:

pip3 install mpld3

Agora que o mpld3 está instalado em sua máquina, podemos importá-lo para nosso script do Python com a seguinte declaração:

import mpld3

Para facilitar a leitura, é considerada uma prática recomendada incluir essa importação junto com o restante das importações na parte superior de seu script. Isso significa que agora sua seção de importação ficará assim:

############################
#Importação das dependências
############################

import pandas as pd
import matplotlib.pyplot as plt
import mpld3

Como transformar uma visualização estática do matplotlib em uma visualização interativa de dados

A principal funcionalidade da biblioteca mpld3 é pegar uma visualização matplotlib existente e transformá-la em algum código HTML que você pode embutir em seu site.

A ferramenta que usamos para isso é o arquivo fig_to_html do mpld3, que aceita um objeto figure do matplotlib como seu único argumento e retorna HTML.

Para usar o método fig_to_html para nosso propósito, basta adicionar o seguinte código ao final do nosso script do Python:

html_str = mpld3.fig_to_html(fig)
Html_file= open("index.html","w")
Html_file.write(html_str)
Html_file.close()

Este código gera o HTML e o salva com o nome de arquivo index.html em seu diretório de trabalho atual. Esta é a aparência disso quando renderizado em uma página da web:

Screenshot-from-2024-03-24-14-28-48

Ao passar o mouse sobre esta visualização, três ícones aparecerão no canto inferior esquerdo. O ícone esquerdo retorna a visualização à sua aparência padrão. O ícone do meio ativa o modo dinâmico. O ícone direito permite cortar e aplicar zoom em um ponto específico da visualização.

Um erro comum ao trabalhar com pandas e mpld3

Ao criar a visualização interativa neste tutorial, você pode encontrar o seguinte erro gerado pelo mpld3:

TypeError: array([ 1.]) is not JSON serializable

Felizmente, existe uma solução bem documentada para esse erro no GitHub.

Você precisa editar o arquivo _display.py encontrado em Lib\site-packages\mpld3 e substituir a classe NumpyEncoder por esta:

class NumpyEncoder(json.JSONEncoder):
    """ Special json encoder for numpy types """

    def default(self, obj):
        if isinstance(obj, (numpy.int_, numpy.intc, numpy.intp, numpy.int8,
            numpy.int16, numpy.int32, numpy.int64, numpy.uint8,
            numpy.uint16,numpy.uint32, numpy.uint64)):
            return int(obj)
        elif isinstance(obj, (numpy.float_, numpy.float16, numpy.float32, 
            numpy.float64)):
            return float(obj)
        try: # Added by ceprio 2018-04-25
            iterable = iter(obj)
        except TypeError:
            pass
        else:
            return list(iterable)
         # Let the base class default method raise the TypeError
        return json.JSONEncoder.default(self, obj)

Depois que essa substituição for feita, seu código deverá funcionar corretamente e seu arquivo index.html deverá ser gerado com êxito.

Reflexões finais

Neste tutorial, você aprendeu como criar visualizações interativas de dados em Python usando as bibliotecas matplotlib e mpld3. Aqui está um resumo específico do que abordamos:

  1. A definição de uma visualização dinâmica de dados
  2. Como instalar e importar a biblioteca mpld3 em Python
  3. Como usar a biblioteca mpld3 para transformar uma visualização do matplotlib em uma visualização dinâmica que você pode embutir em seu site
  4. Como corrigir um erro comum que os usuários da biblioteca mpld3 enfrentam

Este tutorial foi escrito por Nick McCullum, que ensina desenvolvimento em Python e JavaScript em seu site.