Matplotlib Widgets PlatoBlockchain Data Intelligence. Pesquisa Vertical. Ai.

Widgets do Matplotlib

Matplotlib não serve apenas para gráficos estáticos. Embora as GUIs sejam normalmente criadas com bibliotecas e estruturas GUI, como PyQtGenericName, TkinterGenericName, Desesperado e wxPython, e embora o Python tenha excelente integração com PyQt, Tkinter e wxPython – não há necessidade de usar nenhum deles para algumas funcionalidades básicas da GUI, por meio de Widgets do Matplotlib.

A matplotlib.widgets módulo possui diversas classes, incluindo a AxesWidget, dos quais Buttons, CheckButtons, Sliders, TextBoxes, etc são derivados. Todos estes aceitam o Axes eles estão sendo adicionados como o único argumento obrigatório do construtor e seu posicionamento deve ser definido manualmente. Uma coisa a notar é que widget são os eixos, então você criará um Axes instância para cada widget.

Outra coisa a notar é que você tem que manter referências aos widgets caso contrário, eles poderão receber lixo coletado.

Cada um deles também pode ser desativado configurando active para False, nesse caso, eles não responderão a nenhum evento, como serem clicados. Dito isto, podemos introduzir um novo tipo de interactividade nas nossas tramas, através de vários elementos e componentes GUI.

Observação: Matplotlib não se destina a ser usado para criação de GUI de alta qualidade, nem para sistemas fáceis de usar. Esses widgets são rudimentares, não têm uma ótima aparência e têm funcionalidade limitada. Eles foram concebidos como uma forma de prototipar e testar coisas, em vez de realmente enviá-las.

Se você já trabalhou com PyQt antes, poderá notar que a sintaxe geral e a abordagem para adicionar esses widgets, bem como conectá-los a manipuladores de eventos, são bastante familiares.

Adicionando botões

Vamos começar com botões - O matplotlib.widgets módulo define um Button aula. Para se conectar a ele, chamamos o on_clicked() função, que executa a função que fornecemos. Assim que um clique for detectado, a função será executada.

Ao criar o botão, atribuímos um Axes a ele, usado para posicionamento. Também podemos passar em um label naquele momento, para adicionar algum texto e anotá-lo para um usuário. O color e hovercolor argumentos definem a cor do botão antes e depois de passar o mouse sobre ele.

Já que cuidamos do posicionamento e do espaço de todos os widgets – vamos criar um Figure e Axes, deixe algum espaçamento na parte inferior para adicionar um botão e trace um gráfico de dispersão vazio. Então, definiremos um EventHandler classe, que possui um único método add_random(). O método gera dois números aleatórios e traça um marcador para eles no Axes criamos antes e chamamos plt.draw(), que redesenha o Figure. Ao atualizar os gráficos, sempre teremos que ligar plt.draw() novamente para realmente atualizá-lo:

import numpy as np
import matplotlib.pyplot as plt
from matplotlib.widgets import Button fig, ax = plt.subplots()
fig.subplots_adjust(bottom=0.2)
plot = ax.scatter([], []) class EventHandler: def add_random(self, event): x = np.random.randint(0, 100) y = np.random.randint(0, 100) ax.scatter(x, y) plt.draw() # Axes for the Button and positioning
# xposition and yposition in percentages, width, height
button_ax = plt.axes([0.7, 0.05, 0.2, 0.07])
# Create Button and assign it to `button_ax` with label
button = Button(button_ax, 'Add Random', color='green', hovercolor='red')
# On a detected click, execute add_random()
button.on_clicked(EventHandler().add_random) plt.show()

Isso resulta em um Figure, com um vazio Axes dentro dele e um botão no canto superior direito da tela, em seu próprio Axes:

Matplotlib Widgets PlatoBlockchain Data Intelligence. Pesquisa Vertical. Ai.

E depois de pressionar o botão algumas dezenas de vezes, nosso ax será preenchido com marcadores aleatórios:

Matplotlib Widgets PlatoBlockchain Data Intelligence. Pesquisa Vertical. Ai.

Em termos mais práticos, poderíamos criar uma ciclo de recursos a serem plotados em cada pressionamento de botão. Isso requer alguns ajustes no EventHandler, bem como outro botão para voltar a esse ciclo.

Vamos usar o Qualidade do Vinho Tinto conjunto de dados novamente e visualize vários recursos em relação ao Álcool recurso. Como não podemos nos preocupar em plotá-los individualmente, escrevendo o código para plotar um recurso em relação ao outro e, em seguida, modificando esse código para plotar outro recurso em relação ao outro.

Criar uma Matriz de Dispersão pode nos ajudar aqui, mas se o conjunto de dados tiver muitos recursos, será bastante ilegível e não iremos longe. Se você gostaria de ter ambos gráficos em grande escala que você pode visualizar e interpretar facilmente, também como ter vários recursos alternando sem nenhum esforço extra – você pode automatizar esse processo com botões:

import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
from matplotlib.widgets import Button fig, ax = plt.subplots()
fig.subplots_adjust(bottom=0.2) df = pd.read_csv('winequality-red.csv')
plot = ax.scatter([], []) class EventHandler: i = 0 # Find and plot next feature, re-draw the Axes def next_feature(self, event): # If the counter is at the end of the columns # Revert it back to 0 to cycle through again if self.i >= len(df.columns): self.i = 0 # Clear Axes from last plot ax.cla() # Plot a feature against a feature located on the `i` column ax.scatter(df['alcohol'], df.iloc[:,self.i]) # Set labels ax.set_xlabel('Alcohol') ax.set_ylabel(df.columns[self.i]) # Increment i self.i += 1 # Update Figure plt.draw() def previous_feature(self, event): # If the counter is at the start of the columns # Revert it back to the last column to cycle through if self.i <= 0: self.i = len(df.columns)-1 ax.cla() ax.scatter(df['alcohol'], df.iloc[:,self.i]) ax.set_xlabel('Alcohol') ax.set_ylabel(df.columns[self.i]) self.i -= 1 plt.draw() # Add buttons
button1_ax = plt.axes([0.7, 0.02, 0.2, 0.07])
next_button = Button(button1_ax, 'Next Feature')
next_button.on_clicked(EventHandler().next_feature) button2_ax = plt.axes([0.45, 0.02, 0.2, 0.07])
previous_button = Button(button2_ax, 'Previous Feature')
previous_button.on_clicked(EventHandler().previous_feature) plt.show()

A EventHandler classe agora tem dois métodos – next_feature() e previous_feature(). Ambos verificam se o contador i atingiu o final ou início da lista de colunas – e para evitar uma IndexError, redefinimos o índice para o valor oposto e simulamos um ciclo. Indo abaixo 0 nos levará de volta ao final da lista de colunas, e ir acima da última coluna nos reverterá para a primeira.

Depois de verificar onde estamos localizados – nós limpar o Axes, já que estaríamos plotando novamente em cima de um gráfico existente sem limpá-lo via cla() (clorelha axes). Alternativamente, você também pode empilhar relações de recursos, plotando-as umas sobre as outras e usando o método cla() instrução ao redefinir o índice no final/início do ciclo.

Depois de limpar o Axes – temos uma tela limpa para pintar com o ax.scatter() função. Neste exemplo, o recurso fixo é Álcool, então está presente em todos os momentos. O outro recurso varia e pode ser acessado através iloc[], passando o índice da coluna. Isso retorna um Series que podemos usar neste gráfico. Da mesma forma, podemos acessar nomes de coluna por meio de seu índice também - df.columns[index], que é usado para definir o rótulo do eixo Y.

Finalmente, aumentamos/diminuímos o contador e chamamos plt.draw() para atualizar o Figure:

Matplotlib Widgets PlatoBlockchain Data Intelligence. Pesquisa Vertical. Ai.

Assim que clicarmos no Próximo recurso botão, o próximo recurso na lista de colunas será plotado em relação Álcool, e as Figure serão devidamente atualizados – os rótulos, marcadores e escala. O mesmo acontece ao contrário - Recurso Anterior percorrerá a lista na direção oposta, permitindo-nos alternar para frente e para trás, com um mecanismo de segurança que zera nosso contador cada vez que chegamos ao final ou início do ciclo.

Adicionando botões de opção e caixas de seleção

botões de rádio são usados ​​para permitir que um usuário selecione um valor fora de vários valores. Apenas um botão de opção pode ser selecionado por vez e normalmente representa uma escolha. Caixas de seleção pode ser usado se você quiser permitir que o usuário selecione várias opções de uma vez.

Observação: Há uma capacidade muito limitada de verificar se uma caixa de seleção está on or WOW!. Na verdade, não há nada fora da caixa. Você só pode verificar se a caixa está prensado or não, o que representa uma séria limitação à forma como pode ser utilizado, uma vez que não temos ideia em que estado se encontrava antes disso. A única alternativa é manter seu próprio contador/verificação do estado atual da caixa com um booleano e alterar a lógica com base nisso.

Isso permitiria, por exemplo, adicionar uma caixa de seleção para cada argumento de personalização de um determinado lote, permitindo ao usuário configurá-los True or False (marcado ou desmarcado) ou qualquer outro mapeamento não conflitante baseado nesses estados.

Porém, como a API é limitada, também nos limitaremos ao uso pretendido – ligar e desligar coisas. Teremos dois recursos, que podemos transformar on e WOW! por meio de uma caixa de seleção. Observe que mesmo esta funcionalidade é limitada a objetos nos quais você pode verificar se estão visíveis ou não.

Por outro lado, não queremos permitir que o usuário aplique duas escalas ao mesmo tempo, ou defina dois limites X de uma vez, pois apenas a instrução chamada segundo na sequência seria aplicada. Para estes – usaríamos botões de opção.

Vamos adicionar alguns botões de opção para permitir que o usuário selecione o intervalo do eixo por meio de alguns botões de opção, mas também permitir que eles transformem visualizações de recursos on e WOW!:

import pandas as pd
import matplotlib.pyplot as plt
from matplotlib.widgets import CheckButtons
from matplotlib.widgets import RadioButtons fig, ax = plt.subplots()
fig.subplots_adjust(bottom=0.2) df = pd.read_csv('winequality-red.csv') # Plot two line plots for two features, and turn them invisible
line1, = ax.plot(df['fixed acidity'], visible=False)
line2, = ax.plot(df['citric acid'], visible=False) class EventHandler: # set_range handler def set_range(label): if (label == 'Small Range'): ax.set_xlim(0, 1600) ax.set_ylim(0, 25) else: ax.set_xlim(0, 1600) ax.set_ylim(0, 50) plt.draw() # Turn off, if on, and on if off def apply_features(label): if (label == 'Fixed Acidity'): line1.set_visible(not line1.get_visible()) elif (label == 'Citric Acid'): line2.set_visible(not line2.get_visible()) plt.draw() # Add radio buttons and checkboxes
ranges_ax = plt.axes([0.7, 0.02, 0.2, 0.1])
range_radio_buttons = RadioButtons(ranges_ax, ('Small Range', 'Large Range'))
range_radio_buttons.on_clicked(EventHandler.set_range) checkboxes_ax = plt.axes([0.4, 0.02, 0.25, 0.1])
checkboxes = CheckButtons(checkboxes_ax, ('Fixed Acidity', 'Citric Acid'))
checkboxes.on_clicked(EventHandler.apply_features) plt.show()

Novamente, temos dois métodos no EventHandler() aula - set_range() e apply_features(). O set_range() método define o intervalo como “pequeno” ou “grande”, ajustando o Axes' Limites X e Y. O apply_features() função altera o visible campo dos gráficos de linha que fizemos anteriormente, com base em seus atuais visible status. Se visible == True, desligamos o Line Plot e vice-versa.

Temos que contar com a capacidade integrada de verificar a visibilidade dos gráficos de linha, uma vez que não podemos verificar se a caixa de seleção foi marcada ou não antes. Essa mesma habilidade pode ser emulada com um status booleano no escopo do EventHandler() classe, que está definida como True e False em cada clique, para tipos de plotagem que não suportam a verificação se estão visíveis imediatamente.

A execução deste código resulta em um Figure com dois conjuntos de botões na parte inferior. Se marcarmos ambas as caixas de seleção, ambos os gráficos de linha aparecerão:

Matplotlib Widgets PlatoBlockchain Data Intelligence. Pesquisa Vertical. Ai.

Podemos desligá-los individualmente:

Matplotlib Widgets PlatoBlockchain Data Intelligence. Pesquisa Vertical. Ai.

E podemos alterar o intervalo do Axes através dos botões de opção:

Matplotlib Widgets PlatoBlockchain Data Intelligence. Pesquisa Vertical. Ai.

Adicionando caixas de texto

Caixas de texto estão acostumados a coletar dados do usuário – e podemos alterar os gráficos com base nesses dados. Por exemplo, podemos pedir a um usuário que insira o nome de um recurso ou que insira uma função para visualizar nosso gráfico. É claro que trabalhar com a entrada do usuário pode ser complicado – sempre há casos extremos a serem observados.

Vamos escrever um script que permita ao usuário inserir um nome do recurso de um conjunto de dados e o Axes atualizações em cada envio para refletir a entrada. Para a conveniência do usuário, informaremos se a entrada não puder corresponder a um nome de coluna:

import pandas as pd
import matplotlib.pyplot as plt
from matplotlib.widgets import TextBox fig, ax = plt.subplots()
fig.subplots_adjust(bottom=0.2) df = pd.read_csv('winequality-red.csv') class EventHandler: def submit(feature_name): if feature_name != "" or feature_name != None: if feature_name in df: ax.cla() ax.plot(df[feature_name]) else: if len(textbox_ax.texts) > 2: del textbox_ax.texts[-1] textbox_ax.text(-2, 0.4, feature_name + ' was not found.') plt.draw() textbox_ax = plt.axes([0.7, 0.02, 0.2, 0.1])
textbox = TextBox(textbox_ax, 'Feature Name')
textbox.on_submit(EventHandler.submit) plt.show()

Temos uma verificação simples para ver se o fornecido feature_name está em branco ou None, nesse caso, não fazemos nada. Caso contrário, verificamos se o feature_name está presente no DataFrame, anexando uma mensagem informando que o recurso não foi encontrado se não estiver presente. Porém, antes de anexar o texto, temos que nos certificar de que a mensagem anterior foi removida, para que a nova não se sobreponha a ela. O axes.texts propriedade é uma lista de todos os Text instâncias em um Axes. Desde o Axes já tem um Text por exemplo, pertencente ao nosso TextBox, não queremos remover nada se houver 2 ou menos Text instâncias presentes – a mensagem de erro e o TextBox rótulo.

Se for acima de dois, já recebemos uma mensagem de erro, que deve ser removida.

Se o recurso is presente no DataFrame, porém, limpamos o Axes e plote:

Matplotlib Widgets PlatoBlockchain Data Intelligence. Pesquisa Vertical. Ai.

Matplotlib Widgets PlatoBlockchain Data Intelligence. Pesquisa Vertical. Ai.

Matplotlib Widgets PlatoBlockchain Data Intelligence. Pesquisa Vertical. Ai.

Adicionando Seletores de Span

Seletores de extensão pode ser usado para permitir que o usuário selecione um intervalo de dados e se concentre nele, definindo os limites do eixo com base nessa seleção. Por padrão, muitas bibliotecas suportam essa funcionalidade, embora, infelizmente, o Matplotlib não o faça e teremos que fazer isso manualmente. Além disso, teremos que adicionar um extra "Redefinir" botão se quisermos zoom out tão bem.

Para adicionar um Seletor de intervalo, não precisamos dedicar um novo Axes para isso – podemos anexá-lo a um já existente, o que faz muito sentido. Ao gerar um SpanSelector, nós fornecemos o Axes ao qual pertence, bem como o manipulador de eventos, seguido por 'horizontal' or 'vertical', que gira o Axes e Seletor de extensão ambos.

A useblit argumento é normalmente definido como True porque melhora o desempenho na maioria dos back-ends. Além disso, adicionamos algumas propriedades de estilo, como definir o alpha do retângulo criado como um Seletor de Span para 0.5 e os votos de facecolor para um bom tab:blue:

import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
from matplotlib.widgets import SpanSelector
from matplotlib.widgets import Button fig, ax = plt.subplots()
fig.subplots_adjust(bottom=0.2) df = pd.read_csv('AmesHousing.csv') ax.scatter(x = df['Year Built'], y = df['Total Bsmt SF'], alpha = 0.6) class EventHandler: def select_horizontal(x, y): ax.set_xlim(x, y) plt.draw() def reset(self): ax.set_xlim(df['Year Built'].min(), df['Year Built'].max()) plt.draw span_horizontal = SpanSelector(ax, EventHandler.select_horizontal, 'horizontal', useblit=True, rectprops=dict(alpha=0.5, facecolor='tab:blue')) button_ax = plt.axes([0.7, 0.02, 0.2, 0.07])
button = Button(button_ax, 'Reset')
button.on_clicked(EventHandler.reset) plt.show()

Executar isso gera um gráfico no qual podemos selecionar vãos e ampliá-los, definindo os limites dos eixos para os valores fornecidos:

Matplotlib Widgets PlatoBlockchain Data Intelligence. Pesquisa Vertical. Ai.

Matplotlib Widgets PlatoBlockchain Data Intelligence. Pesquisa Vertical. Ai.

Matplotlib Widgets PlatoBlockchain Data Intelligence. Pesquisa Vertical. Ai.

Adicionando controles deslizantes

Controles permitem que os usuários selecionem entre vários valores intuitivamente deslizando um marcador e selecionando um valor. Normalmente, os controles deslizantes são usados ​​para atualizar continuamente algum valor em um gráfico, como seu intervalo or até mesmo um recurso. Por exemplo, você pode ajustar o valor de uma constante por meio de um controle deslizante, o que, por sua vez, afeta uma função que depende dessa constante.

Vamos escrever um script que nos permita alterar os limites dos eixos Y e X, através de um controle deslizante, que nos permitirá alterar a perspectiva a partir da qual estamos visualizando nossos dados:

import pandas as pd
import matplotlib.pyplot as plt
from matplotlib.widgets import Slider fig, ax = plt.subplots()
fig.subplots_adjust(bottom=0.2, left=0.2) df = pd.read_csv('winequality-red.csv')
plot, = ax.plot(df['volatile acidity']) class EventHandler: def update(val): ax.set_ylim(0, yslider.val) ax.set_xlim(0, xslider.val) plt.draw() xslider_ax = plt.axes([0.35, 0.03, 0.5, 0.07])
xslider = Slider( ax=xslider_ax, label="X-limit", valmin=0, valmax=len(df['volatile acidity']), valinit=len(df['volatile acidity']), orientation="horizontal"
) yslider_ax = plt.axes([0.03, 0.2, 0.07, 0.5])
yslider = Slider( ax=yslider_ax, label="Y-limit", valmin=0, valmax=3, valinit=1.5, orientation="vertical"
) xslider.on_changed(EventHandler.update)
yslider.on_changed(EventHandler.update) plt.show()

Ajustamos o preenchimento para permitir um controle deslizante à esquerda e na parte inferior do Axese plotou um gráfico de linha simples. Adicionar um controle deslizante exige que façamos um Axes para ele, como acontece com a maioria dos outros widgets, e atribua-o ao ax argumento do Slider através do construtor. Além disso, podemos definir os valores mínimo, máximo e inicial do controle deslizante. Normalmente, esses intervalos serão dinâmicos, com base nos dados que você está plotando, mas também podem ter valores escalares definidos manualmente.

Finalmente, Sliders podem ser orientados horizontalmente ou verticalmente. Como eles devem ser continuamente atualizados através de um toque do mouse – o on_changed() A função é usada para acionar uma resposta quando um usuário fornece uma entrada. Nós ajustamos o EventHandler aula com um update() função que simplesmente ajusta os valores dos limites X e Y com base no value dos respectivos controles deslizantes.

A execução deste código produzirá um gráfico com dois controles deslizantes, que podemos usar para alterar o escopo do Axes:

Matplotlib Widgets PlatoBlockchain Data Intelligence. Pesquisa Vertical. Ai.

Matplotlib Widgets PlatoBlockchain Data Intelligence. Pesquisa Vertical. Ai.

Matplotlib Widgets PlatoBlockchain Data Intelligence. Pesquisa Vertical. Ai.

Carimbo de hora:

Mais de Abuso de pilha