-
-
Notifications
You must be signed in to change notification settings - Fork 2k
Description
(porting across from other repo plotly/plotly.py#5443)
Description
I would like to request the ability to specify a dash style (e.g., "dash", "dot", "dashdot") for the border line of markers in scatter plots.
Currently, the marker.line object only supports properties like color and width. It does not support dash, unlike line traces or shapes.
Attempting to set marker=dict(line=dict(dash="dash")) currently raises a ValueError.
Why should this feature be added?
This feature is essential for creating clear visual distinctions in scatter plots without relying solely on color or marker symbols.
Use Case:
In data imputation or time-series analysis, it is common to visualize "missing" or "inferred" data points alongside original data.
- Original Data: Solid markers.
- Imputed/Inferred Data: Markers with a dashed outline (often hollow or lighter fill).
Current Limitations:
- Shapes: Using
layout.shapes(circles) allows for dashed borders, but shapes are defined in data coordinates. This causes circles to distort into ellipses when the x and y axes have different scales (common in time series). - Markers: Markers maintain their aspect ratio (perfect circles) and fixed pixel size regardless of zoom, which is desired, but they cannot (currently) have dashed borders.
Adding dash support to marker.line would bridge this gap, allowing for perfect, fixed-size circles with dashed outlines.
Mocks/Designs
Proposed API usage:
import plotly.graph_objects as go
fig = go.Figure(
go.Scatter(
mode="markers",
x=[1, 2, 3],
y=[1, 2, 3],
marker=dict(
size=20,
color="white",
line=dict(
color="red",
width=2,
dash="dash" # <--- Proposed Feature
)
)
)
)Example of what I am trying to achieve:
And this is as close as I can get with the current marker options (solid line):
import plotly.express as px
import pandas as pd
import numpy as np
dat = pd.DataFrame(
{
"time": [1, 2, 3, 4, 5, 6],
"all": [1, 7.5, 5.5, 4.8, 5.5, 7],
"missing": [False, False, True, True, False, False],
},
).assign(
value=lambda df: np.where(df["missing"], np.nan, df["all"]),
missing=lambda df: np.where(df["missing"], df["all"], np.nan),
)
(
px.line()
.add_scatter(
x=dat["time"],
y=dat["all"],
mode="lines",
name="all",
line=dict(shape="spline", smoothing=1.3, color="teal", width=3, dash="dash"),
)
.add_scatter(
x=dat["time"],
y=dat["value"],
mode="markers",
name="value",
marker=dict(color="teal", size=30),
)
.add_scatter(
x=dat["time"],
y=dat["missing"],
mode="markers",
name="missing",
marker=dict(
symbol="circle",
color="lightgrey",
size=30,
line=dict(
color="teal",
width=2,
# dash="dash", # <-- Proposed feature to be added here
),
),
)
.update_layout(
showlegend=False,
xaxis=dict(showgrid=False, showticklabels=False, showline=False, ticks=""),
yaxis=dict(showgrid=False, showticklabels=False, showline=False, ticks=""),
)
.show()
)
