Plotly-shapes: een gids voor annoteren en stijlen van grafieken
Leer hoe je je dataverhaal versterkt met Plotly-shapes. Deze gids biedt een volledige walkthrough voor het toevoegen en stijlen van annotaties in Python, van basisrechthoeken en -lijnen tot geavanceerde interactieve geometrieën.
Plotly is een van de krachtigste en populairste Python-bibliotheken voor het maken van interactieve grafieken. Basisgrafieken maken met Plotly is eenvoudig, maar echt impactvolle datavisualisaties vragen vaak om extra elementen die de aandacht van de kijker sturen en belangrijke context bieden. Daar komen Plotly-shapes goed van pas.
Shapes zijn grafische elementen zoals rechthoeken, lijnen en cirkels die je boven op je Plotly-figuren kunt tekenen om te annoteren, te highlighten en cruciale context toe te voegen. Ze zijn de sleutel om een standaardplot te verheffen tot een rijke, inzichtelijke visualisatie van publicatieniveau.
Afbeelding door de auteur
In dit artikel bekijken we alles wat je moet weten over plotly-shapes, van basisimplementatie tot geavanceerde aanpassingstechnieken. Voor wie nieuw is met Plotly is vertrouwd raken met de high-level interface een goede eerste stap, en deze cursus Introduction to Data Visualization with Plotly in Python helpt je de basis onder de knie te krijgen voordat je dieper duikt in aanpassingen zoals shapes.
Wat zijn Plotly-shapes?
Plotly-shapes zijn vectorafbeeldingen die op een figuur worden getekend om extra context te bieden of specifieke gebieden te markeren. Deze annotaties zijn belangrijk om grafieken te bouwen die niet alleen visueel aantrekkelijk zijn, maar ook rijk aan informatie.
Het belang van shapes in datavisualisatie
In datavisualisatie is helderheid cruciaal. Terwijl grafieken zoals scatterplots of staafdiagrammen de data tonen, helpen shapes het verhaal achter de data te vertellen. Ze hebben twee primaire functies:
Datatrends highlighten: Shapes kunnen de aandacht vestigen op sleutelperiodes of -gebeurtenissen in je data. Zo kun je bijvoorbeeld een recessieperiode arceren met een rechthoek op een tijdreeksdiagram van het bbp, of een lijn tekenen om een belangrijke beleidswijziging te markeren. Deze visuele aanwijzing helpt de kijker direct de impact van externe factoren op de data te begrijpen.
Contextuele annotaties bieden: Shapes kunnen specifieke datapunten of clusters omcirkelen of aanwijzen, zoals uitschieters, interessante groepen of kritieke drempels. Denk aan een kwaliteitscontrolekaart waarop je cirkels gebruikt om metingen te markeren die buiten de toegestane marges vallen. Dit maakt de interpretatie van de data sneller en intuïtiever.
Wil je in één oogopslag de meest gebruikte visualisaties zien, wanneer je ze gebruikt en hun typische use-cases? Bekijk dan onze Data Visualization-cheat sheet.
Overzicht van shapetypen in Plotly
Plotly ondersteunt verschillende geometrische shapetypen die je aan de layout van een figuur kunt toevoegen. Elk type wordt gedefinieerd door zijn type en specifieke coördinatenparameters.
Hier is een korte blik op de belangrijkste shapes:
Rechthoek (type: 'rect'): Gedefinieerd door twee tegenoverliggende hoeken (x0, y0) en (x1, y1). Rechthoeken zijn perfect om interessegebieden te arceren of een specifiek datavenster te highlighten.
Lijn (type: 'line'): Gedefinieerd door een startpunt (x0, y0) en een eindpunt (x1, y1). Lijnen zijn uitstekend voor trendlijnen, drempels of referentiemarkeringen.
Cirkel (type: 'circle'): Gedefinieerd door een middelpunt (x0, y0) en een straal. Cirkels zijn ideaal om individuele datapunten of kleine clusters te benadrukken. Let op: een cirkel maken vereist vaak een gelijke beeldverhouding voor de assen (fig.update_layout(yaxis_scaleanchor="x")) om te voorkomen dat hij op een ovaal lijkt.
Pad (type: 'path'): Gedefinieerd door een SVG-padstring. Paden laten je complexe, vrije vormen tekenen, inclusief polygonen. Je geeft een reeks commando's (zoals M voor move, L voor line to, Z voor pad sluiten) om elke gewenste vorm te tekenen. Dit is de meest veelzijdige optie voor aangepaste geometrische annotaties.
Deze basistypen begrijpen is de eerste stap naar het beheersen van visuele annotaties in je Plotly-figuren.
Shapes toevoegen aan Plotly-grafieken
Plotly-shapes implementeren in je visualisaties draait om twee primaire benaderingen: de add_shape()-methode voor individuele shapes en de update_layout()-aanpak voor meerdere shapes. Beide bieden unieke voordelen afhankelijk van je use-case en workflowvoorkeuren. Laten we zien hoe je shapes toevoegt met de methode add_shape().
Hoe shapes toevoegen met add_shape()?
De primaire methode om een enkele shape toe te voegen aan een Plotly-figuur is fig.add_shape(). De methode add_shape() is een functie van het object plotly.graph_objects.Figure. Je maakt eerst je basisfiguur (bijv. een scatterplot of lijngrafiek) en roept daarna deze methode aan om de shape erbovenop te leggen.
Dit is vooral handig wanneer je shapes programmatisch wilt toevoegen op basis van bepaalde voorwaarden of datawaarden. Laten we een eenvoudig voorbeeld bekijken waarin we een specifiek gebied op een tijdreeksplot highlighten.
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()Mogelijk gemaakt door
Output:
De plotly-add_shape()-functionaliteit wordt vooral krachtig als je het coördinatensysteem begrijpt. Shapes kunnen naar verschillende coördinatensystemen verwijzen met de parameters xref en yref. Ze bepalen het coördinatenkader: gebruik 'x'/'y' om waarden in data-eenheden te interpreteren, of 'paper' om het genormaliseerde plotgebied te gebruiken waarbij 0 – 1 de volledige breedte/hoogte van linksonder naar rechtsboven beslaat. Laten we de bovenstaande grafiek aanpassen met deze parameters zoals hieronder getoond:
# 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)")Mogelijk gemaakt door
Output:
Rechthoeken en lijnen aanpassen
Rechthoeken en lijnen zijn de meest gebruikte shapes voor annotatie. Plotly biedt uitgebreide opties om hun uiterlijk te regelen. Voor een snel naslagwerk van veelgebruikte Plotly-syntax is de Plotly Express Cheat Sheet van onschatbare waarde. Laten we bekijken hoe je deze shapes aanpast.
Aanpassen van rechthoek-shapes
Rechthoeken worden gedefinieerd door twee punten (x0,y0 en x1, y1). Je kunt de vulling en de rand apart stylen.
# 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)Mogelijk gemaakt door
Output:
Aanpassen van lijn-shapes
Lijnen kun je toevoegen met de speciale methoden ‘add_hline’ en ‘add_vline’ voor horizontale en verticale lijnen die de volledige plot beslaan, of met de algemene methode ‘add_shape’ voor meer precieze controle. Laten we een voorbeeld bekijken:
# 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"))Mogelijk gemaakt door
Output:
Deze voorbeelden laten zien hoe je eenvoudig fundamentele Plotly-shapes toevoegt en stijlt om je grafieken informatiever te maken.
Geavanceerde configuratie en aanpassing
Naast het toevoegen van basale shapes biedt Plotly krachtige tools om meerdere shapes te beheren en hun visuele hiërarchie te bepalen. Deze geavanceerde functies zijn essentieel voor het creëren van complexe, gelaagde en dynamische visualisaties. Laten we enkele manieren bekijken om de grafieken te configureren en aan te passen.
plotly.update_layout gebruiken voor dynamische updates
Hoewel de add_shape()-methode perfect is om shapes één voor één toe te voegen, is de methode update_layout() efficiënter om een verzameling shapes te beheren, vooral wanneer ze programmatisch worden gegenereerd. In plaats van voor elke shape een functie aan te roepen, kun je een lijst met shape-dictionaries rechtstreeks doorgeven aan het argument shapes binnen update_layout().
Laten we een voorbeeld zien van het gebruik van deze methode:
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 areadict(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 eventdict(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()Mogelijk gemaakt door
Output:
Deze methode is vooral krachtig voor dynamische toepassingen, zoals een Dash-dashboard waar shapes moeten veranderen op basis van gebruikersinvoer. Je kunt een nieuwe lijst met shape-objecten genereren en de layout in één schone handeling updaten. Deze aanpak houdt je code overzichtelijk en is doorgaans performanter om in één keer een groot aantal shapes toe te voegen.
Layering en z-indexcontrole
Wanneer je shapes toevoegt aan een plot, is het belangrijk te bepalen of ze bovenop of achter je data verschijnen. Plotly beheert dit via de eigenschap layer. Hoewel het geen fijne z-index is zoals in CSS, biedt het essentiële controle over de visuele stapeling.
De eigenschap layer kan twee waarden hebben:
'above': De shape wordt bovenop datatraces getekend. Dit is de standaardinstelling en handig voor annotaties die duidelijk zichtbaar moeten zijn.
'below': De shape wordt onder datatraces en rasterlijnen getekend. Dit is ideaal voor achtergrondarcering of het highlighten van gebieden zonder de datapunten zelf te bedekken.
De volgorde van shapes binnen de shapes-lijst is ook van belang: shapes die later in de lijst staan, worden bovenop eerder gedefinieerde shapes getekend (binnen dezelfde layer).
Hier is een voorbeeld dat het effect van layering laat zien:
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()Mogelijk gemaakt door
Output:
Zoals je ziet zit de roze rechthoek achter de markers, terwijl de groene cirkel het datapunt overlapt.
Deze layout- en layeringtechnieken beheersen is een belangrijk onderdeel van het maken van geavanceerdere en interactieve datavisualisaties met Plotly. Voor wie in R werkt, gelden vergelijkbare concepten, zoals behandeld in Intermediate Interactive Data Visualization with Plotly in R.
Interactief shapes bewerken
Een van de krachtigste features van Plotly is de interactiviteit. Je kunt Plotly-shapes bewerkbaar maken, zodat gebruikers ze direct op de plot kunnen slepen, schalen en roteren. Deze functie schakel je in door editable=True te zetten binnen de definitie van de shape. Laten we zien hoe je dat doet:
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) which you will see when hovering over the graph with the mouse.# and the plot's config can ensure editing tools are available.
fig.show(config={'edits':{'shapePosition':True}})Mogelijk gemaakt door
Output:
Interactieve shapes zijn ontzettend nuttig voor exploratieve data-analyse. Zo kan een gebruiker een rechthoek over verschillende perioden slepen om bijbehorende samenvattende statistieken in realtime te laten updaten in een Dash-app. Of een cirkel vergroten/verkleinen om een ander cluster punten te selecteren voor verder onderzoek.
Hoewel krachtig, houd er rekening mee dat veelvuldig gebruik van bewerkbare shapes prestatie-implicaties kan hebben in complexe webapplicaties. Voor het maken van echt dynamische, door de gebruiker gestuurde tools zijn ze echter onmisbaar.
Interactiviteit verkennen is een belangrijk onderdeel van moderne datavisualisatie, een onderwerp dat uitgebreid wordt behandeld in cursussen zoals Interactive Data Visualization with Plotly in R, die veel principes deelt met de Python-tegenhanger.
Plotly integreren met andere bibliotheken
Hoewel de ingebouwde shapes van Plotly veelzijdig zijn, heb je soms zeer complexe of aangepaste geometrieën nodig. Door te integreren met gespecialiseerde bibliotheken zoals Shapely kun je geavanceerde polygonen definiëren en ze als aangepaste Plotly-shapes aan je visualisaties toevoegen.
Shapely gebruiken voor geavanceerde geometrische shapes
Shapely is een krachtige Python-bibliotheek voor de bewerking en analyse van vlakke geometrische objecten. Het is de go-to tool voor computationele geometrie, vaak gebruikt in geospatiale analyses. Je kunt er ingewikkelde vormen mee maken, zoals een unie van twee overlappende cirkels of een polygoon met een gat, en die vervolgens in Plotly visualiseren.
Het proces omvat twee hoofdstappen:
Definieer de complexe vorm met Shapely.
Haal de coördinaten uit het Shapely-object en vorm ze om tot een SVG-padstring, die Plotly kan renderen met type: 'path'.
Een SVG-padstring is een mini-taal om te tekenen. Ze gebruikt commando's zoals M (moveto) om een startpunt te zetten, L (lineto) om een lijn naar een nieuw punt te trekken, en Z om het pad te sluiten door een lijn terug naar het begin te tekenen.
Laten we zien hoe je een polygoon met een uitsparing maakt en toevoegt aan een Plotly-figuur.
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 inzip(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 inzip(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()Mogelijk gemaakt door
Output:
Deze techniek is van onschatbare waarde voor geospatiale toepassingen, zoals het plotten van aangepaste verkoopregio's, of in wetenschappelijke contexten waar je onregelmatige interessegebieden wilt highlighten.
Begrijpen hoe verschillende type dataplots worden gemaakt en hoe je ze kunt verrijken met dit soort tools is een fundamentele vaardigheid voor elke dataprofessional. Je kunt meer leren over verschillende plottypes in deze gids over hoe je ze in Python maakt.
Styling en esthetische aanpassing
De standaardweergave van Plotly-shapes is functioneel, maar het stylen ervan is belangrijk om een verzorgde, professioneel ogende visualisatie te maken. Doordacht gebruik van kleur, transparantie en vullingen kan de leesbaarheid en esthetiek aanzienlijk verbeteren.
Kleur, transparantie en patronenvullingen
Plotly geeft je fijne controle over het uiterlijk van shapes, zodat je ze kunt afstemmen op het kleurenschema en de vormentaal van je plot.
Voor nauwkeurige controle over kleur en transparantie is het gebruik van de RGBA-kleurspecificatie (Rood, Groen, Blauw, Alpha) sterk aan te raden. Het a-kanaal regelt de dekking, waarbij een waarde van 1 volledig ondoorzichtig is en 0 volledig transparant.
Dit is essentieel voor subtiele highlights, waarbij de shape context toevoegt zonder de onderliggende data volledig te verbergen. Je kunt RGBA-waarden als string meegeven, zoals 'rgba(255, 99, 71, 0.5)'. Laten we een voorbeeld bekijken:
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)inenumerate(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()Mogelijk gemaakt door
Output:
Strategieën om patronenvullingen te simuleren
Hoewel Plotly geen patronenvullingen native ondersteunt, kunnen dataprofessionals complexe vullingen simuleren met creatieve technieken. Zo kunnen we patronen in de plot creëren met een functie zoals hieronder:
Een gradiëntachtig effect maken vereist strategisch stapelen van meerdere shapes met variërende transparantie. We kunnen dit creëren met dezelfde strategie die we voor de patronen gebruikten, zoals hieronder getoond:
defcreate_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 stringsdefparse_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)ifisinstance(start_color,str)else start_color
end_rgb = parse_rgb(end_color)ifisinstance(end_color,str)else end_color
band_height =(y1 - y0)/ num_bands
for i inrange(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()Mogelijk gemaakt door
Output:
Probleemoplossing en optimalisatie
Hoewel het toevoegen van Plotly-shapes doorgaans eenvoudig is, kun je problemen ondervinden met uitlijning of performance, vooral in complexe plots. Deze veelvoorkomende valkuilen begrijpen en aanpakken bespaart je veel tijd en moeite.
Veelvoorkomende problemen met shape-uitlijning
Een van de meest voorkomende uitdagingen is om shapes precies te laten verschijnen waar jij ze wilt. Een lijn die de volledige breedte van de plot zou moeten beslaan, kan tekortschieten, of een rechthoek lijnt niet uit met de rasterlijnen zoals verwacht. Deze problemen komen bijna altijd voort uit onjuiste coördinatenreferenties.
Plotly gebruikt twee coördinatensystemen voor het plaatsen van shapes:
Datacoördinaten (xref: 'x', yref: 'y'): Dit is de standaard. De positie van de shape is gekoppeld aan de waarden op de x- en y-as. Bijvoorbeeld, x0=50 plaatst het punt op de 50-markering van de x-as.
Papiercoördinaten (xref: 'paper', yref: 'paper'): De positie is relatief aan het plotgebied zelf, waar 0 het begin is (linker-/onderrand) en 1 het einde (rechter-/bovenzijde). Dit systeem is onafhankelijk van datapunten of asbereiken.
Het probleem: Je wilt een horizontale lijn tekenen over de hele plot op y=10. Als je die definieert met x0 en x1 in datacoördinaten, beslaat ze slechts het huidige asbereik. Als de gebruiker zoomt of panned, reikt de lijn niet tot de nieuwe randen.
De oplossing: Gebruik 'paper'-coördinaten voor de as die je volledig wilt laten beslaan, om een shape over de volledige breedte of hoogte van het plotgebied te trekken.
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()Mogelijk gemaakt door
Output:
Controleer altijd je xref- en yref-eigenschappen om te zorgen dat je shapes zich gedragen zoals verwacht tijdens gebruikersinteractie, zoals zoomen en pannen.
Prestatieoverwegingen
Als je een handvol shapes aan een plot toevoegt, is de performance-impact te verwaarlozen. Maar het toevoegen van honderden of duizenden shapes kan de rendering en interactiviteit aanzienlijk vertragen. Elke shape is een afzonderlijk SVG-element (Scalable Vector Graphics) dat aan de DOM van de webpagina wordt toegevoegd. Een groot aantal DOM-elementen belast de browser.
Hier zijn strategieën om de performance te optimaliseren:
Beperk het aantal shapes: De eenvoudigste oplossing. Als je duizenden rechthoekige gebieden wilt visualiseren, overweeg dan of een ander grafiektype, zoals een go.Heatmap, dezelfde informatie efficiënter kan weergeven als één enkele trace in plaats van duizenden shape-objecten.
Gebruik update_layout voor bulktoevoegingen: Zoals eerder vermeld is het toevoegen van een lijst met shapes via fig.update_layout(shapes=...) performanter dan fig.add_shape() in een lus aan te roepen.
Overweeg WebGL-traces voor data: Hoewel shapes zelf als SVG worden gerenderd, kun je de algehele performance van een complexe plot verbeteren door WebGL-gebaseerde traces (bijv. go.Scattergl) te gebruiken voor je hoofddata. Dit verplaatst de datarendering naar de GPU, waardoor de CPU soepeler de SVG-shapes kan afhandelen. Dit is nuttig wanneer je een enorme hoeveelheid datapunten hebt én een gematigd aantal shapes.
Voor de meeste use-cases is het de kunst om bewust om te gaan met het aantal unieke shape-elementen dat je creëert. Voordat je duizenden Plotly-shapes in een lus toevoegt, sta even stil en bedenk of er een productievere visualisatiestrategie bestaat.
Conclusie
Plotly-shapes beheersen transformeert je grafieken van simpele datavertegenwoordigingen naar meeslepende, contextrijke verhalen. We hebben gekeken van het tekenen van basislijnen en -rechthoeken tot het stapelen van complexe, interactieve geometrieën.
Door deze technieken toe te passen, kun je de focus van je publiek sturen, cruciale inzichten highlighten en intuïtievere visualisaties bouwen die helder en impactvol communiceren.
Plotly-shapes worden gebruikt om annotaties zoals lijnen, rechthoeken en cirkels toe te voegen om belangrijke datagebieden in een grafiek te highlighten.
Hoe voeg je meerdere shapes toe in Plotly?⌄
Je kunt efficiënt meerdere shapes toevoegen door een lijst met shape-dictionaries door te geven aan het attribuut shapes in fig.update_layout().
Hoe teken je een verticale lijn in Plotly?⌄
Je kunt een volledige verticale lijn tekenen door type='line' te gebruiken en de eigenschap yref='paper' in te stellen om de volledige plothoogte te beslaan.
Kun je een shape achter de data plaatsen in Plotly?⌄
Ja, je kunt een shape achter datatraces plaatsen door de eigenschap layer op 'below' te zetten.
Hoe voeg je een shape toe aan slechts één subplot in Plotly?⌄
Je kunt een shape aan slechts één subplot toevoegen door de argumenten xrefen yrefop te geven in de definitie ervan.
Ik ben contentschrijver op het gebied van data science. Ik maak graag content over AI/ML/DS-onderwerpen. Ook ontdek ik nieuwe AI-tools en schrijf ik erover.
Plotly is een van de krachtigste en populairste Python-bibliotheken voor het maken van interactieve grafieken. Basisgrafieken maken met Plotly is eenvoudig, maar echt impactvolle datavisualisaties vragen vaak om extra elementen die de aandacht van de kijker sturen en belangrijke context bieden. Daar komen Plotly-shapes goed van pas.
Shapes zijn grafische elementen zoals rechthoeken, lijnen en cirkels die je boven op je Plotly-figuren kunt tekenen om te annoteren, te highlighten en cruciale context toe te voegen. Ze zijn de sleutel om een standaardplot te verheffen tot een rijke, inzichtelijke visualisatie van publicatieniveau.
Afbeelding door de auteur
In dit artikel bekijken we alles wat je moet weten over plotly-shapes, van basisimplementatie tot geavanceerde aanpassingstechnieken. Voor wie nieuw is met Plotly is vertrouwd raken met de high-level interface een goede eerste stap, en deze cursus Introduction to Data Visualization with Plotly in Python helpt je de basis onder de knie te krijgen voordat je dieper duikt in aanpassingen zoals shapes.
Wat zijn Plotly-shapes?
Plotly-shapes zijn vectorafbeeldingen die op een figuur worden getekend om extra context te bieden of specifieke gebieden te markeren. Deze annotaties zijn belangrijk om grafieken te bouwen die niet alleen visueel aantrekkelijk zijn, maar ook rijk aan informatie.
Het belang van shapes in datavisualisatie
In datavisualisatie is helderheid cruciaal. Terwijl grafieken zoals scatterplots of staafdiagrammen de data tonen, helpen shapes het verhaal achter de data te vertellen. Ze hebben twee primaire functies:
Wil je in één oogopslag de meest gebruikte visualisaties zien, wanneer je ze gebruikt en hun typische use-cases? Bekijk dan onze Data Visualization-cheat sheet.
Overzicht van shapetypen in Plotly
Plotly ondersteunt verschillende geometrische shapetypen die je aan de layout van een figuur kunt toevoegen. Elk type wordt gedefinieerd door zijn
typeen specifieke coördinatenparameters.Hier is een korte blik op de belangrijkste shapes:
type: 'rect'): Gedefinieerd door twee tegenoverliggende hoeken (x0,y0) en (x1,y1). Rechthoeken zijn perfect om interessegebieden te arceren of een specifiek datavenster te highlighten.type: 'line'): Gedefinieerd door een startpunt (x0,y0) en een eindpunt (x1,y1). Lijnen zijn uitstekend voor trendlijnen, drempels of referentiemarkeringen.type: 'circle'): Gedefinieerd door een middelpunt (x0,y0) en een straal. Cirkels zijn ideaal om individuele datapunten of kleine clusters te benadrukken. Let op: een cirkel maken vereist vaak een gelijke beeldverhouding voor de assen (fig.update_layout(yaxis_scaleanchor="x")) om te voorkomen dat hij op een ovaal lijkt.type: 'path'): Gedefinieerd door een SVG-padstring. Paden laten je complexe, vrije vormen tekenen, inclusief polygonen. Je geeft een reeks commando's (zoalsMvoor move,Lvoor line to,Zvoor pad sluiten) om elke gewenste vorm te tekenen. Dit is de meest veelzijdige optie voor aangepaste geometrische annotaties.Deze basistypen begrijpen is de eerste stap naar het beheersen van visuele annotaties in je Plotly-figuren.
Shapes toevoegen aan Plotly-grafieken
Plotly-shapes implementeren in je visualisaties draait om twee primaire benaderingen: de
add_shape()-methode voor individuele shapes en deupdate_layout()-aanpak voor meerdere shapes. Beide bieden unieke voordelen afhankelijk van je use-case en workflowvoorkeuren. Laten we zien hoe je shapes toevoegt met de methodeadd_shape().Hoe shapes toevoegen met add_shape()?
De primaire methode om een enkele shape toe te voegen aan een Plotly-figuur is
fig.add_shape(). De methodeadd_shape()is een functie van het objectplotly.graph_objects.Figure. Je maakt eerst je basisfiguur (bijv. een scatterplot of lijngrafiek) en roept daarna deze methode aan om de shape erbovenop te leggen.Dit is vooral handig wanneer je shapes programmatisch wilt toevoegen op basis van bepaalde voorwaarden of datawaarden. Laten we een eenvoudig voorbeeld bekijken waarin we een specifiek gebied op een tijdreeksplot highlighten.
Output:
De plotly-
add_shape()-functionaliteit wordt vooral krachtig als je het coördinatensysteem begrijpt. Shapes kunnen naar verschillende coördinatensystemen verwijzen met de parametersxrefenyref. Ze bepalen het coördinatenkader: gebruik'x'/'y'om waarden in data-eenheden te interpreteren, of'paper'om het genormaliseerde plotgebied te gebruiken waarbij 0 – 1 de volledige breedte/hoogte van linksonder naar rechtsboven beslaat. Laten we de bovenstaande grafiek aanpassen met deze parameters zoals hieronder getoond:Output:
Rechthoeken en lijnen aanpassen
Rechthoeken en lijnen zijn de meest gebruikte shapes voor annotatie. Plotly biedt uitgebreide opties om hun uiterlijk te regelen. Voor een snel naslagwerk van veelgebruikte Plotly-syntax is de Plotly Express Cheat Sheet van onschatbare waarde. Laten we bekijken hoe je deze shapes aanpast.
Aanpassen van rechthoek-shapes
Rechthoeken worden gedefinieerd door twee punten (
x0,y0enx1,y1). Je kunt de vulling en de rand apart stylen.Output:
Aanpassen van lijn-shapes
Lijnen kun je toevoegen met de speciale methoden ‘add_hline’ en ‘add_vline’ voor horizontale en verticale lijnen die de volledige plot beslaan, of met de algemene methode ‘add_shape’ voor meer precieze controle. Laten we een voorbeeld bekijken:
Output:
Deze voorbeelden laten zien hoe je eenvoudig fundamentele Plotly-shapes toevoegt en stijlt om je grafieken informatiever te maken.
Geavanceerde configuratie en aanpassing
Naast het toevoegen van basale shapes biedt Plotly krachtige tools om meerdere shapes te beheren en hun visuele hiërarchie te bepalen. Deze geavanceerde functies zijn essentieel voor het creëren van complexe, gelaagde en dynamische visualisaties. Laten we enkele manieren bekijken om de grafieken te configureren en aan te passen.
plotly.update_layout gebruiken voor dynamische updates
Hoewel de
add_shape()-methode perfect is om shapes één voor één toe te voegen, is de methodeupdate_layout()efficiënter om een verzameling shapes te beheren, vooral wanneer ze programmatisch worden gegenereerd. In plaats van voor elke shape een functie aan te roepen, kun je een lijst met shape-dictionaries rechtstreeks doorgeven aan het argumentshapesbinnenupdate_layout().Laten we een voorbeeld zien van het gebruik van deze methode:
Output:
Deze methode is vooral krachtig voor dynamische toepassingen, zoals een Dash-dashboard waar shapes moeten veranderen op basis van gebruikersinvoer. Je kunt een nieuwe lijst met shape-objecten genereren en de layout in één schone handeling updaten. Deze aanpak houdt je code overzichtelijk en is doorgaans performanter om in één keer een groot aantal shapes toe te voegen.
Layering en z-indexcontrole
Wanneer je shapes toevoegt aan een plot, is het belangrijk te bepalen of ze bovenop of achter je data verschijnen. Plotly beheert dit via de eigenschap layer. Hoewel het geen fijne
z-indexis zoals in CSS, biedt het essentiële controle over de visuele stapeling.De eigenschap
layerkan twee waarden hebben:'above': De shape wordt bovenop datatraces getekend. Dit is de standaardinstelling en handig voor annotaties die duidelijk zichtbaar moeten zijn.'below': De shape wordt onder datatraces en rasterlijnen getekend. Dit is ideaal voor achtergrondarcering of het highlighten van gebieden zonder de datapunten zelf te bedekken.De volgorde van shapes binnen de shapes-lijst is ook van belang: shapes die later in de lijst staan, worden bovenop eerder gedefinieerde shapes getekend (binnen dezelfde layer).
Hier is een voorbeeld dat het effect van layering laat zien:
Output:
Zoals je ziet zit de roze rechthoek achter de markers, terwijl de groene cirkel het datapunt overlapt.
Deze layout- en layeringtechnieken beheersen is een belangrijk onderdeel van het maken van geavanceerdere en interactieve datavisualisaties met Plotly. Voor wie in R werkt, gelden vergelijkbare concepten, zoals behandeld in Intermediate Interactive Data Visualization with Plotly in R.
Interactief shapes bewerken
Een van de krachtigste features van Plotly is de interactiviteit. Je kunt Plotly-shapes bewerkbaar maken, zodat gebruikers ze direct op de plot kunnen slepen, schalen en roteren. Deze functie schakel je in door
editable=Truete zetten binnen de definitie van de shape. Laten we zien hoe je dat doet:Output:
Interactieve shapes zijn ontzettend nuttig voor exploratieve data-analyse. Zo kan een gebruiker een rechthoek over verschillende perioden slepen om bijbehorende samenvattende statistieken in realtime te laten updaten in een Dash-app. Of een cirkel vergroten/verkleinen om een ander cluster punten te selecteren voor verder onderzoek.
Hoewel krachtig, houd er rekening mee dat veelvuldig gebruik van bewerkbare shapes prestatie-implicaties kan hebben in complexe webapplicaties. Voor het maken van echt dynamische, door de gebruiker gestuurde tools zijn ze echter onmisbaar.
Interactiviteit verkennen is een belangrijk onderdeel van moderne datavisualisatie, een onderwerp dat uitgebreid wordt behandeld in cursussen zoals Interactive Data Visualization with Plotly in R, die veel principes deelt met de Python-tegenhanger.
Plotly integreren met andere bibliotheken
Hoewel de ingebouwde shapes van Plotly veelzijdig zijn, heb je soms zeer complexe of aangepaste geometrieën nodig. Door te integreren met gespecialiseerde bibliotheken zoals Shapely kun je geavanceerde polygonen definiëren en ze als aangepaste Plotly-shapes aan je visualisaties toevoegen.
Shapely gebruiken voor geavanceerde geometrische shapes
Shapely is een krachtige Python-bibliotheek voor de bewerking en analyse van vlakke geometrische objecten. Het is de go-to tool voor computationele geometrie, vaak gebruikt in geospatiale analyses. Je kunt er ingewikkelde vormen mee maken, zoals een unie van twee overlappende cirkels of een polygoon met een gat, en die vervolgens in Plotly visualiseren.
Het proces omvat twee hoofdstappen:
type: 'path'.Een SVG-padstring is een mini-taal om te tekenen. Ze gebruikt commando's zoals
M(moveto) om een startpunt te zetten,L(lineto) om een lijn naar een nieuw punt te trekken, enZom het pad te sluiten door een lijn terug naar het begin te tekenen.Laten we zien hoe je een polygoon met een uitsparing maakt en toevoegt aan een Plotly-figuur.
Output:
Deze techniek is van onschatbare waarde voor geospatiale toepassingen, zoals het plotten van aangepaste verkoopregio's, of in wetenschappelijke contexten waar je onregelmatige interessegebieden wilt highlighten.
Begrijpen hoe verschillende type dataplots worden gemaakt en hoe je ze kunt verrijken met dit soort tools is een fundamentele vaardigheid voor elke dataprofessional. Je kunt meer leren over verschillende plottypes in deze gids over hoe je ze in Python maakt.
Styling en esthetische aanpassing
De standaardweergave van Plotly-shapes is functioneel, maar het stylen ervan is belangrijk om een verzorgde, professioneel ogende visualisatie te maken. Doordacht gebruik van kleur, transparantie en vullingen kan de leesbaarheid en esthetiek aanzienlijk verbeteren.
Kleur, transparantie en patronenvullingen
Plotly geeft je fijne controle over het uiterlijk van shapes, zodat je ze kunt afstemmen op het kleurenschema en de vormentaal van je plot.
Voor nauwkeurige controle over kleur en transparantie is het gebruik van de RGBA-kleurspecificatie (Rood, Groen, Blauw, Alpha) sterk aan te raden. Het
a-kanaal regelt de dekking, waarbij een waarde van1volledig ondoorzichtig is en0volledig transparant.Dit is essentieel voor subtiele highlights, waarbij de shape context toevoegt zonder de onderliggende data volledig te verbergen. Je kunt RGBA-waarden als string meegeven, zoals
'rgba(255, 99, 71, 0.5)'. Laten we een voorbeeld bekijken:Output:
Strategieën om patronenvullingen te simuleren
Hoewel Plotly geen patronenvullingen native ondersteunt, kunnen dataprofessionals complexe vullingen simuleren met creatieve technieken. Zo kunnen we patronen in de plot creëren met een functie zoals hieronder:
Gradiënteffect simuleren
Een gradiëntachtig effect maken vereist strategisch stapelen van meerdere shapes met variërende transparantie. We kunnen dit creëren met dezelfde strategie die we voor de patronen gebruikten, zoals hieronder getoond:
Output:
Probleemoplossing en optimalisatie
Hoewel het toevoegen van Plotly-shapes doorgaans eenvoudig is, kun je problemen ondervinden met uitlijning of performance, vooral in complexe plots. Deze veelvoorkomende valkuilen begrijpen en aanpakken bespaart je veel tijd en moeite.
Veelvoorkomende problemen met shape-uitlijning
Een van de meest voorkomende uitdagingen is om shapes precies te laten verschijnen waar jij ze wilt. Een lijn die de volledige breedte van de plot zou moeten beslaan, kan tekortschieten, of een rechthoek lijnt niet uit met de rasterlijnen zoals verwacht. Deze problemen komen bijna altijd voort uit onjuiste coördinatenreferenties.
Plotly gebruikt twee coördinatensystemen voor het plaatsen van shapes:
xref: 'x', yref: 'y'): Dit is de standaard. De positie van de shape is gekoppeld aan de waarden op de x- en y-as. Bijvoorbeeld,x0=50plaatst het punt op de 50-markering van de x-as.xref: 'paper', yref: 'paper'): De positie is relatief aan het plotgebied zelf, waar 0 het begin is (linker-/onderrand) en 1 het einde (rechter-/bovenzijde). Dit systeem is onafhankelijk van datapunten of asbereiken.Het probleem: Je wilt een horizontale lijn tekenen over de hele plot op
y=10. Als je die definieert metx0enx1in datacoördinaten, beslaat ze slechts het huidige asbereik. Als de gebruiker zoomt of panned, reikt de lijn niet tot de nieuwe randen.De oplossing: Gebruik
'paper'-coördinaten voor de as die je volledig wilt laten beslaan, om een shape over de volledige breedte of hoogte van het plotgebied te trekken.Output:
Controleer altijd je
xref- enyref-eigenschappen om te zorgen dat je shapes zich gedragen zoals verwacht tijdens gebruikersinteractie, zoals zoomen en pannen.Prestatieoverwegingen
Als je een handvol shapes aan een plot toevoegt, is de performance-impact te verwaarlozen. Maar het toevoegen van honderden of duizenden shapes kan de rendering en interactiviteit aanzienlijk vertragen. Elke shape is een afzonderlijk SVG-element (Scalable Vector Graphics) dat aan de DOM van de webpagina wordt toegevoegd. Een groot aantal DOM-elementen belast de browser.
Hier zijn strategieën om de performance te optimaliseren:
go.Heatmap, dezelfde informatie efficiënter kan weergeven als één enkele trace in plaats van duizenden shape-objecten.update_layoutvoor bulktoevoegingen: Zoals eerder vermeld is het toevoegen van een lijst met shapes viafig.update_layout(shapes=...)performanter danfig.add_shape()in een lus aan te roepen.go.Scattergl) te gebruiken voor je hoofddata. Dit verplaatst de datarendering naar de GPU, waardoor de CPU soepeler de SVG-shapes kan afhandelen. Dit is nuttig wanneer je een enorme hoeveelheid datapunten hebt én een gematigd aantal shapes.Voor de meeste use-cases is het de kunst om bewust om te gaan met het aantal unieke shape-elementen dat je creëert. Voordat je duizenden Plotly-shapes in een lus toevoegt, sta even stil en bedenk of er een productievere visualisatiestrategie bestaat.
Conclusie
Plotly-shapes beheersen transformeert je grafieken van simpele datavertegenwoordigingen naar meeslepende, contextrijke verhalen. We hebben gekeken van het tekenen van basislijnen en -rechthoeken tot het stapelen van complexe, interactieve geometrieën.
Door deze technieken toe te passen, kun je de focus van je publiek sturen, cruciale inzichten highlighten en intuïtievere visualisaties bouwen die helder en impactvol communiceren.
Klaar om deze skills toe te passen? Ga vandaag nog aan de slag met krachtigere visualisaties door de cursus Introduction to Data Visualization with Plotly in Python te verkennen en je kennis in de praktijk te brengen.