Search code examples
mathgraphplotly

How to draw axes with arrows for X and Y in plotly


Which seams a basic operation, I couldn't find it docs. Even searching for Google images doesn't show a single example of a chart with typical school-like axes.

How to draw X Y axes with arrows which pass the 0 point? Just like a basic chart known from school blackboards, ideally with ticks, function name, it's formula in LateX etc. Just the basics of a function graph.

My current workaround which gives me lines axes:

X = np.linspace(-10, 10, 2000)
Y = [f(P, x) for x in X]


fig = px.line(x=X, y=Y, range_y=[-50, 50], range_x=[-5, 5])
fig.update_layout(showlegend=False, xaxis_title='', yaxis_title='')
fig.add_vline(0)
fig.add_hline(0)
fig.show()

Example from wikipedia (sadly without arrows) (https://en.wikipedia.org/wiki/Graph_of_a_function): enter image description here

Another example (has arrows, but ugly and no ticks): enter image description here

My hand-drawn example: enter image description here


Solution

  • I took your wishes and created a code with a graph that depicts a general curve, not the curve in your question. The function annotations follow your question. There seems to be no way to bring the xy axis to the center at this time. Create a new annotation and update the graph.

    • Customize graph size to square.
    • Hide xy-axis ticks. Set xy-axis to zero point and set axis titles.
    • Create new xy-axis ticks manually and in dictionary format.
    • Create a new xy-axis arrow manually in dictionary format.
    • Combine the dictionaries and set them as annotations.
    • Add function formulas as annotations.
    import numpy as np
    import plotly.express as px
    
    t = np.linspace(-5.0, 5.0, 1000)
    s = t**3
    
    fig = px.line(x=t, y=s)
    
    fig.update_layout(autosize=True,
                      width=600,
                      height=600,
                      template=None,
                      showlegend=False,
                      xaxis_title='',
                      yaxis_title='',
                      xaxis=dict(showticklabels=False),
                      yaxis=dict(showticklabels=False)
                     )
    
    fig.update_layout(xaxis=dict(zeroline=True,
                                 zerolinecolor='black',
                                 title_text="X",
                                ))
    
    fig.update_layout(yaxis=dict(zeroline=True,
                                 zerolinecolor='black',
                                 title_text="Y",
                                ))
    
    xaxes_dict = [dict(x=x, y=-7, xref="x", yref="y", text=str(x), showarrow=False) for x in np.arange(-4, 5, 2)]
    yaxes_dict = [dict(x=-0.5, y=y, xref="x", yref="y", text=str(y), showarrow=False) for y in np.arange(-100, 101, 50)]
    
    arrowx_dict = [dict(x=0, y=140, ax=0, ay=20, showarrow=True, xref='x', yref='y', arrowhead=5, arrowsize=1.5, arrowwidth=1)]
    arrowy_dict = [dict(x=5, y=0, ax=-20, ay=0, showarrow=True, xref='x', yref='y', arrowhead=5, arrowsize=1.5, arrowwidth=1)]
    
    fig.update_layout(annotations=xaxes_dict+yaxes_dict+arrowx_dict+arrowy_dict)
    
    fig.add_annotation(x=0.5, y=50,
                       xref='x',
                       yref='y',
                       text=r'$f(x)=\frac{x^3+3x^2-6x-8}{4}$',
                       font=dict(size=16),
                       showarrow=False,
                       yshift=10)
    
    fig.show()
    

    enter image description here