How do I create a graph that has a continuous axes with matplotlib?

by shaana   Last Updated October 11, 2018 19:26 PM

I'm trying to create an interactive graphs. I can't figure out how to plot a quadratic graph that is continuous - as in if you zoom out/move across the axes, the equation is plotted there, not just between 2 x points, so it's continuous.

I've got this so far.

import matplotlib.pyplot as plt

xcoord=[]
ycoord=[]

for x in range(0,10):
    y=(2*x)**2 + 2*x + 4
    xcoord.append(x)
    ycoord.append(y)

plt.plot(xcoord,ycoord)
plt.show()


Answers 3


continuity is hard to replicate, it sounds like what you need is to increase the plot density. Change your loop and use numpy

import numpy as np
numpy.linspace
import matplotlib.pyplot as plt

xcoord=[]
ycoord=[]

for x in np.linspace(0,10,1000):
    y=(2*x)**2 + 2*x + 4
    xcoord.append(x)
    ycoord.append(y)

plt.plot(xcoord,ycoord)
plt.show()
Yuca
Yuca
July 31, 2018 19:18 PM

If I understand your question, you want to dynamically recalculate the content of the plot (the coordinates) based on the current axis pan / zoom. Doing so requires using event handling to detect a change in axis limits, then recalculate the coordinates with a predefined number of points between these limits, and finally updating the plot accordingly

import matplotlib as mpl
import matplotlib.pyplot as plt
import numpy as np


def my_func(x):
    return (2 * x) ** 2 + 2 * x + 4


def on_lims_change(axes):
    xmin, xmax = axes.get_xlim()
    new_x = np.linspace(xmin, xmax, 1000)
    new_y = my_func(new_x)
    l.set_data(new_x, new_y)


fig, ax = plt.subplots()
xcoord = np.linspace(0, 10, 1000)
ycoord = my_func(xcoord)
l, = ax.plot(xcoord, ycoord, 'r-')

ax.callbacks.connect('xlim_changed', on_lims_change)
ax.callbacks.connect('ylim_changed', on_lims_change)

on_lims_change(ax)
plt.show()

Credits go to @ImportanceOfBeingErnest for showing how to connect an event handler on changes to the axes limits in this answer

Diziet Asahi
Diziet Asahi
July 31, 2018 20:19 PM

Matplotlib is does not plot functions, but rather points. Of course any continuous function can be approximated by points if they are only dense enough.

The problem indeed occurs when zooming into the plot, in which case formerly dense points will spread out and a polygonial structure will be observable. Inversely when zooming out, it may happen that the function has not been evaluated outside a specific range and hence the plot will stay mostly empty.

A solution is to evaluate the function each time the axis limits change, notably on a grid which covers the complete axis range and has as many points as there are pixels. We can find out the number of pixels from the figure size and dpi.

To show the effect, I added a sinusodial function with a low amplitude here.

import numpy as np
import matplotlib.pyplot as plt

func = lambda x: (2*x)**2 + 2*x + -4 + 0.2*np.sin(x*20)

fig, ax = plt.subplots()
ax.axis([-8,8,-100,400])
line, = ax.plot([])

def update(evt=None):
    xmin,xmax = ax.get_xlim()
    npoints = fig.get_size_inches()[0]*fig.dpi
    x = np.linspace(xmin, xmax, npoints)
    y = func(x)
    line.set_data(x,y)
    fig.canvas.draw_idle()

ax.callbacks.connect('xlim_changed', update)    
fig.canvas.mpl_connect("resize_event", update)
plt.show()

enter image description here

ImportanceOfBeingErnest
ImportanceOfBeingErnest
July 31, 2018 20:38 PM

Related Questions


How to annotate text along curved lines in Python?

Updated April 21, 2015 22:11 PM


Invalid RGBA argument: nan

Updated October 19, 2017 23:26 PM

Can't plot dates in graph with Python

Updated February 17, 2018 22:26 PM