Curso
O Plotly é uma das bibliotecas Python mais poderosas e populares para a criação de gráficos interativos. Embora a criação de gráficos básicos com o Plotly seja simples, as visualizações de dados realmente impactantes geralmente exigem elementos adicionais que orientem a atenção do visualizador e forneçam um contexto importante. É nesse ponto que as formas do Plotly se tornam valiosas.
As formas são elementos gráficos, como retângulos, linhas e círculos, que você pode desenhar sobre as figuras do Plotly para fazer anotações, destacar e adicionar contexto crucial. Eles são a chave para transformar um gráfico padrão em uma visualização rica, perspicaz e com qualidade de publicação.
Imagem do autor
Neste artigo, veremos tudo o que você precisa saber sobre formas de plotagem, desde a implementação básica até técnicas avançadas de personalização. Para aqueles que estão começando a usar o Plotly, sentir-se confortável com sua interface de alto nível é um ótimo primeiro passo, e este Introdução à visualização de dados com Plotly em Python pode ajudar você a dominar os fundamentos antes de se aprofundar em personalizações como formas.
O que são formas de plotagem?
Formas de plotagem são gráficos vetoriais desenhados em uma figura para fornecer contexto adicional ou destacar áreas específicas. Essas anotações são importantes para a criação de gráficos que não sejam apenas visualmente atraentes, mas também ricos em informações.
A importância das formas na visualização de dados
Na visualização de dados, a clareza é importante. Enquanto os gráficos, como os de dispersão ou de barras, apresentam os dados, as formas ajudam a contar a história por trás dos dados. Eles têm duas funções principais:
- Destacar tendências de dados: As formas podem chamar a atenção para períodos ou eventos importantes em seus dados. Por exemplo, você pode usar um retângulo para sombrear um período de recessão em um gráfico de série temporal do PIB ou desenhar uma linha para marcar uma mudança significativa na política. Essa dica visual ajuda o visualizador a entender imediatamente o impacto de fatores externos nos dados.
- Fornecimento de anotações contextuais: As formas podem circundar ou apontar para pontos ou grupos de dados específicos, como outliers, grupos de interesse ou limites críticos. Imagine um gráfico de controle de qualidade em que você usa círculos para sinalizar as medições que estão fora dos limites aceitáveis. Isso torna a interpretação dos dados mais rápida e intuitiva.
Se você quiser dar uma olhada rápida nas visualizações de dados mais comuns, quando usá-las e seus casos de uso mais comuns, confira nossa Folha de consulta de visualização de dados.
Visão geral dos tipos de formas no Plotly
O Plotly oferece suporte a vários tipos de formas geométricas que podem ser adicionadas ao layout de uma figura. Cada um deles é definido por seu site type
e por parâmetros de coordenadas específicos.
Aqui está uma breve olhada nas formas primárias:
- Retângulo (
type: 'rect'
): Definido por dois cantos opostos (x0
,y0
) e (x1
,y1
). Os retângulos são perfeitos para sombrear regiões de interesse ou destacar uma janela específica de dados. - Linha (
type: 'line'
): Definido por um ponto inicial (x0
,y0
) e um ponto final (x1
,y1
). As linhas são excelentes para criar linhas de tendência, limites ou marcas de referência. - Círculo (
type: 'circle'
): Definido por um centro (x0
,y0
) e um raio. Os círculos são ideais para enfatizar pontos de dados individuais ou pequenos grupos. Observe que a criação de um círculo geralmente envolve a definição de uma proporção igual para os eixos (fig.update_layout(yaxis_scaleanchor="x")
) para evitar que ele se pareça com uma forma oval. - Caminho (
type: 'path'
): Definido por uma string de caminho SVG. Os caminhos permitem que você desenhe formas complexas e livres, inclusive polígonos. Você fornece uma sequência de comandos (comoM
para mover,L
para alinhar a,Z
para fechar caminho) para desenhar qualquer forma que precisar. Essa é a opção mais versátil para criar anotações geométricas personalizadas.
Compreender esses tipos básicos é a primeira etapa para que você domine as anotações visuais em suas figuras do Plotly.
Adicionando formas aos gráficos do Plotly
A implementação de formas de plotagem em suas visualizações envolve a compreensão de duas abordagens principais: o método add_shape()
para formas individuais e a abordagem update_layout()
para várias formas. Ambos os métodos oferecem vantagens exclusivas, dependendo do seu caso de uso específico e das preferências de fluxo de trabalho. Vamos ver como você pode adicionar formas usando o método add_shape()
.
Como adicionar formas usando add_shape()?
O principal método para adicionar uma única forma a uma figura do Plotly é fig.add_shape()
. O método add_shape()
é uma função do objeto plotly.graph_objects.Figure
. Primeiro, você cria a figura de base (por exemplo, um gráfico de dispersão ou de linhas) e, em seguida, chama esse método para colocar a forma na parte superior.
Isso é particularmente útil quando você precisa adicionar formas de forma programática com base em determinadas condições ou valores de dados. Vejamos um exemplo básico em que destacamos uma região específica em um gráfico de série temporal.
import plotly.graph_objects as go
import numpy as np
# Create sample data
x = np.linspace(0, 10, 100)
y = np.sin(x) + np.random.normal(0, 0.1, 100)
# Create base figure
fig = go.Figure()
fig.add_trace(go.Scatter(x=x, y=y, mode='lines', name='Signal'))
# Add a shape using add_shape method
fig.add_shape(
type="rect", # Shape type
x0=2, x1=4, # X coordinates
y0=-2, y1=2, # Y coordinates
fillcolor="rgba(255, 0, 0, 0.3)", # Fill color with transparency
line=dict(color="red", width=2) # Border styling
)
fig.show()
Saída:
A funcionalidade do plotly add_shape()
torna-se particularmente poderosa quando você entende o sistema de coordenadas. As formas podem fazer referência a diferentes sistemas de coordenadas usando os parâmetros xref
e yref
. Vamos modificar o gráfico acima usando esses parâmetros, conforme mostrado abaixo:
# Shape referenced to data coordinates (default)
fig.add_shape(type="line", x0=1, x1=9, y0=0, y1=0,
line=dict(color="green", width=3))
# Shape referenced to paper coordinates (0-1 scale)
fig.add_shape(type="rect", xref="paper", yref="paper",
x0=0.1, x1=0.9, y0=0.1, y1=0.9,
fillcolor="rgba(0, 0, 255, 0.1)")
Saída:
Personalização de retângulos e linhas
Retângulos e linhas são as formas mais comumente usadas para anotações. O Plotly oferece amplas opções de personalização para você controlar sua aparência. Para que você tenha uma referência rápida sobre a sintaxe comum do Plotly, a Folha de dicas do Plotly Express é um recurso inestimável. Vamos ver como você pode personalizar essas formas.
Personalização do formato do retângulo
Os retângulos são definidos por dois pontos (x0
,y0
e x1
, y1
). Você pode estilizar o preenchimento e a borda separadamente.
# Advanced rectangle customization
fig.add_shape(
type="rect",
x0=3, x1=7,
y0=-1.5, y1=1.5,
# Fill properties
fillcolor="rgba(50, 171, 96, 0.4)",
# Line properties
line=dict(
color="darkgreen",
width=3,
dash="dashdot" # Options: solid, dot, dash, longdash, dashdot
),
# Layer control
layer="below" # Options: above, below
)
Saída:
Personalização da forma da linha
As linhas podem ser adicionadas usando os métodos especializados 'add_hline' e 'add_vline' para linhas horizontais e verticais que abrangem todo o gráfico, ou por meio do método geral 'add_shape' para um controle mais preciso. Vejamos um exemplo:
# Horizontal threshold lines
fig.add_hline(y=1.0, line_dash="dash", line_color="red",
annotation_text="Upper Threshold")
fig.add_hline(y=-1.0, line_dash="dash", line_color="red",
annotation_text="Lower Threshold")
# Custom diagonal line
fig.add_shape(
type="line",
x0=0, x1=10,
y0=-2, y1=2,
line=dict(
color="purple",
width=4,
dash="longdashdot"
)
)
Saída:
Esses exemplos demonstram a facilidade com que você pode adicionar e estilizar formas fundamentais do Plotly para tornar seus gráficos mais informativos.
Configuração e personalização avançadas
Além de adicionar formas básicas, o Plotly oferece ferramentas avançadas para gerenciar várias formas e controlar sua hierarquia visual. Esses recursos avançados são essenciais para a criação de visualizações complexas, em camadas e dinâmicas. Vejamos algumas maneiras de configurar e personalizar os gráficos.
Usando plotly.update_layout para atualizações dinâmicas
Embora o método add_shape()
seja perfeito para adicionar formas uma a uma, o método update_layout()
é uma maneira mais eficiente de gerenciar uma coleção de formas, especialmente quando elas são geradas programaticamente. Em vez de chamar uma função para cada forma, você pode passar uma lista de dicionários de formas diretamente para o argumento shapes
em update_layout()
.
Vamos ver um exemplo de uso desse método:
import plotly.graph_objects as go
import numpy as np
# Sample scatter plot data
x_data = np.linspace(0, 10, 50)
y_data = np.sin(x_data) + np.random.normal(0, 0.1, 50)
fig = go.Figure(data=go.Scatter(x=x_data, y=y_data, mode='markers', name='Data Points'))
# Define a list of shapes to add
shapes_to_add = [
# A rectangle highlighting a peak area
dict(
type="rect",
x0=1, x1=2.5, y0=0.8, y1=1.2,
fillcolor="rgba(255, 165, 0, 0.4)",
line_width=0
),
# A vertical line marking an event
dict(
type="line",
x0=7.5, x1=7.5, y0=0, y1=1,
yref="paper", # Span the full plot height
line=dict(color="red", width=2, dash="dot")
)
]
# Add all shapes at once using update_layout
fig.update_layout(
shapes=shapes_to_add
)
fig.show()
Saída:
Esse método é particularmente eficiente para aplicativos dinâmicos, como um painel do Dash, em que as formas precisam mudar com base na entrada do usuário. Você pode gerar uma nova lista de objetos de forma e atualizar o layout em uma operação única e limpa. Essa abordagem mantém seu código organizado e, em geral, é mais eficiente para adicionar um grande número de formas de uma só vez.
Controle de camadas e z-index
Quando você adiciona formas a um gráfico, é importante controlar se elas aparecem em cima ou atrás dos dados. O Plotly gerencia isso por meio da propriedade de camada. Embora não seja um z-index
granular como no CSS, ele oferece controle essencial sobre o empilhamento visual.
A propriedade layer
pode ser definida com um de dois valores:
'above'
: A forma é desenhada sobre os traços de dados. Essa é a configuração padrão e é útil para anotações que devem ser claramente visíveis.'below'
: A forma é desenhada abaixo dos traços de dados e das linhas de grade. Isso é ideal para sombrear o fundo ou destacar regiões sem obscurecer os próprios pontos de dados.
A ordem das formas dentro da seção formas também é importante: as formas definidas posteriormente na lista serão desenhadas sobre as definidas anteriormente (na mesma camada).
Aqui está um exemplo que demonstra o efeito das camadas:
import plotly.graph_objects as go
fig = go.Figure(data=go.Scatter(x=[1, 2, 3, 4, 5], y=[5, 3, 4, 2, 6], mode='markers', marker_size=20, name='Data'))
# Add a shape BELOW the data points
fig.add_shape(
type="rect",
x0=2.5, y0=2.5, x1=4.5, y1=4.5,
fillcolor="LightPink",
opacity=0.8,
layer="below", # Key parameter
line_width=0
)
# Add a shape ABOVE the data points
fig.add_shape(
type="circle",
x0=0.5, y0=4.5, x1=1.5, y1=5.5,
fillcolor="LightSeaGreen",
opacity=0.6,
layer="above", # Key parameter
line_width=0
)
fig.update_layout(
xaxis=dict(showgrid=False), # Turn off gridlines to see effect clearly
yaxis=dict(showgrid=False)
)
fig.show()
Saída:
Como você pode ver, o retângulo rosa fica atrás dos marcadores, enquanto o círculo verde sobrepõe o ponto de dados.
Se você dominar essas técnicas de layout e camadas, será fundamental para criar visualizações de dados mais avançadas e interativas com o Plotly. Para quem trabalha em R, aplicam-se conceitos semelhantes, conforme explorado em Intermediate Interactive Data Visualization with Plotly in R.
Edição interativa de formas
Um dos recursos mais poderosos do Plotly é sua interatividade. Você pode tornar as formas do Plotly editáveis, permitindo que os usuários as arrastem, redimensionem e girem diretamente no gráfico. Esse recurso é ativado pela configuração editable=True
na definição da forma. Vamos ver um exemplo de como fazer isso:
import plotly.graph_objects as go
import numpy as np
# Create a scatter plot
fig = go.Figure(go.Scatter(
x=np.random.rand(100),
y=np.random.rand(100),
mode='markers'
))
# Add a draggable rectangle
fig.add_shape(
type="rect",
x0=0.2, y0=0.2, x1=0.5, y1=0.5,
line=dict(color="RoyalBlue", width=2),
fillcolor="LightSkyBlue",
opacity=0.5,
editable=True # This makes the shape interactive
)
fig.update_layout(
xaxis=dict(range=[0, 1]),
yaxis=dict(range=[0, 1]),
# The 'newshape' button in the modebar allows drawing new shapes
# The config dictionary enables editing of existing shapes
dragmode='select'
)
# To enable editing, the modebar must be visible (default)
# and the plot's config can ensure editing tools are available.
fig.show(config={'edits': {'shapePosition': True}})
Saída:
As formas interativas são incrivelmente úteis para a análise exploratória de dados. Por exemplo, um usuário poderia arrastar um retângulo sobre diferentes períodos de tempo para ver as estatísticas resumidas correspondentes atualizadas em tempo real em um aplicativo Dash. Ou, eles podem redimensionar um círculo para selecionar um grupo diferente de pontos para uma investigação mais aprofundada.
Embora seja eficiente, lembre-se de que o uso intenso de formas editáveis pode ter implicações de desempenho em aplicativos da Web complexos. No entanto, para criar ferramentas realmente dinâmicas e orientadas ao usuário, elas são indispensáveis.
A exploração da interatividade é uma parte importante da visualização de dados moderna, um tópico bem abordado em cursos como Visualização interativa de dados com Plotly em R, que compartilha muitos princípios com seu equivalente em Python.
Integração do Plotly com outras bibliotecas
Embora as formas integradas do Plotly sejam versáteis, às vezes você precisa criar geometrias altamente complexas ou personalizadas. Ao integrar-se a bibliotecas especializadas, como a Shapely, você pode definir polígonos sofisticados e adicioná-los às suas visualizações como formas personalizadas do Plotly.
Usando o Shapely para formas geométricas avançadas
Shapely é uma biblioteca Python avançada para a manipulação e análise de objetos geométricos planos. É a ferramenta ideal para geometria computacional, usada com frequência em análises geoespaciais. Você pode usá-lo para criar formas complexas, como uma união de dois círculos sobrepostos ou um polígono com um furo, e depois visualizá-las no Plotly.
O processo envolve duas etapas principais:
- Defina a forma complexa usando o Shapely.
- Extraia as coordenadas do objeto Shapely e formate-as como uma string de caminho SVG, que o Plotly pode renderizar usando
type: 'path'
.
Uma string de caminho SVG é uma mini-linguagem para desenho. Ele usa comandos como M
(moveto) para definir um ponto de partida, L
(lineto) para desenhar uma linha até um novo ponto e Z
para fechar o caminho desenhando uma linha de volta ao início.
Vamos ver como você pode criar um polígono com um recorte e adicioná-lo a uma figura do Plotly.
import plotly.graph_objects as go
from shapely.geometry import Polygon
# 1. Create a complex shape using Shapely
# An outer rectangle
outer_coords = [(1, 1), (1, 5), (8, 5), (8, 1)]
# An inner rectangle (this will be the "hole")
inner_coords = [(3, 2), (3, 4), (6, 4), (6, 2)]
# Define the polygon with a hole
polygon_with_hole = Polygon(outer_coords, [inner_coords])
# 2. Extract coordinates and build the SVG path string
# The exterior path
exterior_x, exterior_y = polygon_with_hole.exterior.xy
path = f"M {exterior_x[0]} {exterior_y[0]}"
for x, y in zip(exterior_x[1:], exterior_y[1:]):
path += f" L {x} {y}"
path += " Z" # Close the exterior path
# The interior path (the hole)
interior_x, interior_y = polygon_with_hole.interiors[0].xy
path += f" M {interior_x[0]} {interior_y[0]}"
for x, y in zip(interior_x[1:], interior_y[1:]):
path += f" L {x} {y}"
path += " Z" # Close the interior path
# Create a figure
fig = go.Figure()
# Add the complex shape to the figure
fig.add_shape(
type="path",
path=path,
fillcolor="LightSeaGreen",
opacity=0.7,
line_color="DarkSlateGray"
)
# You can add data to see how the shape interacts with it
fig.add_trace(go.Scatter(
x=[2, 7, 4.5],
y=[3, 3, 1.5],
mode='markers',
marker=dict(size=15, color='DarkRed')
))
# Use scaleanchor to ensure the shape's aspect ratio is preserved
fig.update_yaxes(scaleanchor="x", scaleratio=1)
fig.show()
Saída:
Essa técnica é inestimável para aplicações geoespaciais, como a plotagem de territórios de vendas personalizados, ou em contextos científicos em que você pode precisar destacar áreas irregulares de interesse.
Entender como são criados os diferentes tipos de gráficos de dados e como eles podem ser aprimorados com essas ferramentas é uma habilidade fundamental para qualquer profissional de dados. Você pode saber mais sobre os diferentes tipos de plotagem neste guia sobre como criá-los em Python.
Personalização de estilo e estética
A aparência padrão das formas do Plotly é funcional, mas a personalização de seu estilo é importante para que você crie uma visualização polida e de aparência profissional. O uso cuidadoso de cores, opacidade e preenchimentos pode melhorar significativamente a legibilidade e o apelo estético.
Preenchimentos de cor, opacidade e padrão
O Plotly oferece a você um controle refinado sobre a aparência das formas, permitindo que você as combine com o esquema de cores e a linguagem de design do seu gráfico.
Para um controle preciso da cor e da transparência, é altamente recomendável usar a especificação de cor RGBA (Red, Green, Blue, Alpha). O canal a
(alfa) controla a opacidade, sendo que um valor de 1
é totalmente opaco e 0
é totalmente transparente .
Isso é essencial para a criação de destaques não intrusivos, em que a forma adiciona contexto sem ocultar completamente os dados que estão por baixo. Você pode fornecer valores RGBA como uma cadeia de caracteres, como 'rgba(255, 99, 71, 0.5)'
. Vamos ver um exemplo:
import plotly.graph_objects as go
import numpy as np
# Create sample data for styling demonstration
x = np.linspace(0, 10, 100)
y1 = np.sin(x) + np.random.normal(0, 0.1, 100)
y2 = np.cos(x) + np.random.normal(0, 0.1, 100)
fig = go.Figure()
fig.add_trace(go.Scatter(x=x, y=y1, name='Signal 1', line=dict(color='blue')))
fig.add_trace(go.Scatter(x=x, y=y2, name='Signal 2', line=dict(color='red')))
# RGBA Color Technique 1: Graduated opacity for depth
opacity_levels = [0.15, 0.25, 0.35]
colors = ['255,0,0', '0,255,0', '0,0,255']
for i, (opacity, color) in enumerate(zip(opacity_levels, colors)):
fig.add_shape(
type="rect",
x0=i*2.5, x1=(i+1)*2.5,
y0=-3, y1=3,
fillcolor=f"rgba({color},{opacity})",
line=dict(color=f"rgb({color})", width=2),
layer="below"
)
# RGBA Technique 2: Color blending for overlapping regions
fig.add_shape(
type="circle",
x0=7.5, x1=9.5,
y0=-1, y1=1,
fillcolor="rgba(255, 255, 0, 0.4)", # Semi-transparent yellow
line=dict(color="orange", width=3),
layer="below"
)
fig.update_layout(
title="Advanced RGBA Color Techniques in Plotly Shapes",
showlegend=True
)
fig.show()
Saída:
Estratégias de simulação de preenchimento de padrões
Embora o Plotly não ofereça suporte nativo a preenchimentos de padrões, os profissionais de dados podem simular padrões de preenchimento complexos usando técnicas criativas. Por exemplo, podemos criar padrões no gráfico usando uma função, conforme mostrado abaixo:
def create_pattern_fill_simulation(fig, x0, x1, y0, y1, pattern_type='diagonal'):
"""Simulate pattern fills using multiple overlapping shapes"""
if pattern_type == 'diagonal':
# Create diagonal line pattern
line_spacing = 0.2
line_width = 1
# Calculate diagonal lines
range_x = x1 - x0
range_y = y1 - y0
num_lines = int((range_x + range_y) / line_spacing)
for i in range(num_lines):
offset = i * line_spacing
# Calculate line endpoints for diagonal pattern
start_x = max(x0, x0 + offset - range_y)
start_y = max(y0, y1 - offset)
end_x = min(x1, x0 + offset)
end_y = min(y1, y1 - offset + range_x)
fig.add_shape(
type="line",
x0=start_x, x1=end_x,
y0=start_y, y1=end_y,
line=dict(color="rgba(0, 0, 0, 0.3)", width=line_width),
layer="above"
)
elif pattern_type == 'crosshatch':
# Create crosshatch pattern
spacing = 0.3
# Vertical lines
x_lines = np.arange(x0, x1, spacing)
for x_line in x_lines:
fig.add_shape(
type="line",
x0=x_line, x1=x_line,
y0=y0, y1=y1,
line=dict(color="rgba(100, 100, 100, 0.4)", width=1),
layer="above"
)
# Horizontal lines
y_lines = np.arange(y0, y1, spacing)
for y_line in y_lines:
fig.add_shape(
type="line",
x0=x0, x1=x1,
y0=y_line, y1=y_line,
line=dict(color="rgba(100, 100, 100, 0.4)", width=1),
layer="above"
)
return fig
# Demonstration of pattern fill simulation
pattern_fig = go.Figure()
pattern_fig.add_trace(go.Scatter(x=[1, 2, 3, 4, 5], y=[2, 4, 3, 5, 1],
mode='lines+markers', name='Data'))
# Add base rectangle
pattern_fig.add_shape(
type="rect",
x0=1.5, x1=3.5,
y0=1, y1=5,
fillcolor="rgba(200, 200, 255, 0.3)",
line=dict(color="blue", width=2),
layer="below"
)
# Apply pattern fill simulation
pattern_fig = create_pattern_fill_simulation(pattern_fig, 1.5, 3.5, 1, 5, 'diagonal')
pattern_fig.show()
Simulação de efeito de gradiente
Para criar efeitos de gradiente, você precisa de camadas estratégicas de várias formas com opacidade variável. Podemos criar usando a mesma estratégia que usamos para criar os padrões, conforme mostrado abaixo:
def create_gradient_effect(fig, x0, x1, y0, y1, start_color, end_color, num_bands=20):
"""Simulate gradient fill using multiple rectangular bands"""
# Parse RGB values from color strings
def parse_rgb(color_str):
if color_str.startswith('rgb('):
values = color_str[4:-1].split(',')
return [int(v.strip()) for v in values]
return [0, 0, 0] # Default to black if parsing fails
start_rgb = parse_rgb(start_color) if isinstance(start_color, str) else start_color
end_rgb = parse_rgb(end_color) if isinstance(end_color, str) else end_color
band_height = (y1 - y0) / num_bands
for i in range(num_bands):
# Calculate interpolated color
ratio = i / (num_bands - 1)
r = int(start_rgb[0] + (end_rgb[0] - start_rgb[0]) * ratio)
g = int(start_rgb[1] + (end_rgb[1] - start_rgb[1]) * ratio)
b = int(start_rgb[2] + (end_rgb[2] - start_rgb[2]) * ratio)
# Calculate band position
band_y0 = y0 + i * band_height
band_y1 = band_y0 + band_height
fig.add_shape(
type="rect",
x0=x0, x1=x1,
y0=band_y0, y1=band_y1,
fillcolor=f"rgba({r}, {g}, {b}, 0.7)",
line=dict(width=0), # No border for seamless gradient
layer="below"
)
return fig
# Apply gradient effect
gradient_fig = go.Figure()
gradient_fig.add_trace(go.Scatter(x=list(range(10)),
y=np.random.randn(10).cumsum(),
mode='lines', name='Time Series'))
gradient_fig = create_gradient_effect(
gradient_fig, 2, 8, -3, 3,
[255, 0, 0], [0, 0, 255], # Red to blue gradient
num_bands=30
)
gradient_fig.show()
Saída:
Solução de problemas e otimização
Embora a adição de formas do Plotly seja geralmente simples, você pode encontrar problemas de alinhamento ou desempenho, especialmente em gráficos complexos. Compreender essas armadilhas comuns e saber como resolvê-las poupará muito tempo e esforço a você.
Problemas comuns com o alinhamento da forma
Um dos desafios mais frequentes é fazer com que as formas apareçam exatamente onde você deseja. Uma linha destinada a abranger toda a largura do gráfico pode não ser suficiente, ou um retângulo pode não se alinhar com as linhas de grade conforme o esperado. Esses problemas quase sempre decorrem de referências incorretas de coordenadas.
O Plotly usa dois sistemas de coordenadas para posicionar formas:
- Coordenadas dos dados (
xref: 'x', yref: 'y'
): Esse é o padrão. A posição da forma está vinculada aos valores nos eixos x e y. Por exemplo,x0=50
coloca o ponto na marca de 50 no eixo x. - Coordenadas do papel (
xref: 'paper', yref: 'paper'
): A posição é relativa à própria área de plotagem, em que 0 é o início (borda esquerda/inferior) e 1 é o fim (borda direita/superior). Esse sistema é independente dos valores de dados ou intervalos de eixos.
O problema: Você deseja desenhar uma linha horizontal em todo o gráfico em y=10
. Se você o definir com x0
e x1
usando coordenadas de dados, ele abrangerá apenas o intervalo do eixo atual. Se o usuário aplicar zoom ou panorâmica, a linha não se estenderá até as novas bordas.
A solução: Para fazer uma forma abranger toda a largura ou altura da área de plotagem, use as coordenadas 'paper'
para o eixo que você deseja abranger.
import plotly.graph_objects as go
fig = go.Figure(data=go.Scatter(x=[0, 10], y=[0, 20]))
# Incorrect: Vertical line that might not span the full height if the user zooms out.
# This line is drawn from y=0 to y=20 in DATA units.
fig.add_shape(
type="line",
x0=5, y0=0, x1=5, y1=20,
line=dict(color="Red", width=2, dash="dash"),
name="Incorrect Line" # Name for legend
)
# Correct: Vertical line that ALWAYS spans the full plot height.
# It is drawn from the bottom edge (0) to the top edge (1) of the PLOT area.
fig.add_shape(
type="line",
x0=8, y0=0, x1=8, y1=1,
yref="paper", # The key to spanning the full height
line=dict(color="Green", width=3),
name="Correct Line"
)
fig.update_layout(title_text="Correctly Spanning the Plot Area")
fig.show()
Saída:
Sempre verifique novamente as propriedades xref
e yref
para garantir que as formas se comportem como esperado durante a interação do usuário, como zoom e panorâmica.
Considerações sobre o desempenho
Se você adicionar um punhado de formas a um gráfico, o impacto no desempenho será insignificante. No entanto, adicionar centenas ou milhares de formas pode tornar a renderização e a interatividade significativamente mais lentas. Cada forma é um elemento SVG (Scalable Vector Graphics) individual adicionado ao DOM da página da Web. Um grande número de elementos DOM sobrecarregará o navegador.
Aqui estão as estratégias para otimizar o desempenho:
- Limite o número de formas: A solução mais simples. Se você precisar visualizar milhares de áreas retangulares, considere se um tipo diferente de gráfico, como um
go.Heatmap
, poderia representar as mesmas informações de forma mais eficiente como um único traço em vez de milhares de objetos de forma. - Use o site
update_layout
para adições em massa: Conforme mencionado anteriormente, adicionar uma lista de formas viafig.update_layout(shapes=...)
é mais eficiente do que chamarfig.add_shape()
em um loop. - Considere os rastreamentos WebGL para dados: Embora as formas em si sejam renderizadas como SVG, você pode melhorar o desempenho geral de um gráfico complexo usando traços baseados em WebGL (por exemplo,
go.Scattergl
) para seus dados principais. Isso transfere a renderização de dados para a GPU, liberando a CPU para lidar com as formas SVG de forma mais suave. Isso é útil quando você tem um grande número de pontos de dados e um número moderado de formas.
Para a maioria dos casos de uso, a chave é estar atento ao número de elementos de forma exclusivos que você está criando. Antes de adicionar milhares de formas do Plotly em um loop, faça uma pausa e considere se existe uma estratégia de visualização com melhor desempenho.
Conclusão
Ao dominar as formas do Plotly, você transforma seus gráficos de simples representações de dados em histórias convincentes e ricas em contexto. Você já viu como desenhar linhas e retângulos básicos e como criar camadas de geometrias complexas e interativas.
Ao aplicar essas técnicas, você pode orientar o foco do seu público, destacar insights essenciais e criar visualizações mais intuitivas que se comuniquem com clareza e impacto.
Você está pronto para aplicar essas habilidades? Comece a criar visualizações mais eficientes hoje mesmo, explorando a seção Introdução à visualização de dados com Plotly em Python e coloque seus conhecimentos à prova.
Perguntas frequentes sobre o Plotly Shapes
Para que são usadas as formas do Plotly?
As formas do Plotly são usadas para adicionar anotações como linhas, retângulos e círculos para destacar regiões de dados importantes em um gráfico.
Como você adiciona várias formas no Plotly?
Você pode adicionar várias formas com eficiência passando uma lista de dicionários de formas para o atributo shapes
em fig.update_layout()
.
Como você desenha uma linha vertical no Plotly?
Você pode desenhar uma linha vertical completa usando type='line'
e definindo a propriedade yref='paper'
para abranger toda a altura do gráfico.
Você pode colocar uma forma por trás dos dados no Plotly?
Sim, você pode colocar uma forma atrás de traços de dados definindo sua propriedade layer
propriedade para 'below'
.
Como você adiciona uma forma a apenas uma subparcela no Plotly?
Você pode adicionar uma forma a uma subparcela específica fornecendo os atributos xref
e yref
em sua definição.
Sou redator de conteúdo de ciência de dados. Adoro criar conteúdo sobre tópicos de IA/ML/DS. Também exploro novas ferramentas de IA e escrevo sobre elas.