"Partial" Axis Range

Inspired by Tufte’s The Visual Display of Quantitative Information:
Is it possible to have a “partial” axis like below (maybe there’s a better name for this):

I don’t mind if the min/max are auto-calculated or if I should populate them myself.

Hi @mingw64 ,

You can make that plot, but off course need custom modification than just scatter plot.

The idea is to hide axis lines and grid lines , then create another line shape to “replace” hidden axis line.
If you want to add tick labels, redefine the tick labels between the min and max value of each axis using tickmode="array" and generate tickvals from min/max value with interval that you want.

Here the example.

import plotly.express as px
import numpy as np

df = px.data.iris()
fig = px.scatter(df, x="sepal_length", y="sepal_width")

x = df.sepal_length
y = df.sepal_width


# get min max, idxmin, and idxmax  each axis 
min_y, max_y = y.min(),y.max()
idxmin_y, idxmax_y = y.idxmin(),y.idxmax()
min_x, max_x = x.min(),x.max()
idxmin_x, idxmax_x = x.idxmin(),x.idxmax()

xaxis_pad = 0.2 # padding from min/max value to axis line
yaxis_pad = 0.2 # padding from min/max value to axis line

# define new range to easier put dashed line in min and max value
new_x_range = (min_x- xaxis_pad, max_x + xaxis_pad)
new_y_range = (min_y- yaxis_pad, max_y + yaxis_pad)


# draw min x line
fig.add_shape(type="line",
    x0=min_x, y0=new_y_range[0], x1=min_x, y1=y.iloc[idxmin_x],
    line=dict(
        color="grey",
        width=2,
        dash="dot",
    )
)

# draw max x line
fig.add_shape(type="line",
    x0=max_x, y0=new_y_range[0], x1=max_x, y1=y.iloc[idxmax_x],
    line=dict(
        color="grey",
        width=2,
        dash="dot",
    )
)

# draw min y line
fig.add_shape(type="line",
    x0=new_x_range[0], y0=min_y, x1=x.iloc[idxmin_y], y1=min_y,
    line=dict(
        color="grey",
        width=2,
        dash="dot",
    )
)

# draw max y line
fig.add_shape(type="line",
    x0=new_x_range[0], y0=max_y, x1=x.iloc[idxmax_y], y1=max_y,
    line=dict(
        color="grey",
        width=2,
        dash="dot",
    )
)

# draw custom x axis line
fig.add_shape(type="line",
    x0=min_x, y0=new_y_range[0], x1=max_x, y1=new_y_range[0],
    line=dict(
        color="grey",
        width=2,
    )
)

# draw custom y axis line
fig.add_shape(type="line",
    x0=new_x_range[0], y0=min_y, x1=new_x_range[0], y1=max_y,
    line=dict(
        color="grey",
        width=2,
    )
)

# set plot background color white
fig.update_layout(plot_bgcolor="white",)

fig.update_xaxes(showline=False, # hide xaxislie
                showgrid=False, # hide grid line
                range=new_x_range, # set xaxis range
                tickmode="array",  tickvals=list(np.arange(min_x, max_x,0.5)) # set x tick labels
            ) 

fig.update_yaxes(showline=False, # hide y axis line
                showgrid=False, # hide grid line
                range=new_y_range, # set yaxis range
                tickmode="array", tickvals=list(np.arange(min_y, max_y,0.5)) # set y tick labels
            )

fig.show()

1 Like

Thank you, this looks amazing!
I will try it in my code.