Plotting Domain Dependent Functions

  • #1
e2m2a
359
14
TL;DR Summary
Can Python matplotlib plot domain dependent functions in one graph?
Is it possible for Python matplotlib to plot in one graph a domain dependent function? For example, suppose there is a function where y=x from 0< x <=5, y = x sq when 5<x<=7 and y=2x+9 when x>7. Is it possible in Python to plot this with one plot on one graph? If so, how would it be done?
 
Last edited:
Technology news on Phys.org
  • #2
e2m2a said:
Is it possible for Python matplotlib to plot in one graph a domain dependent function? For example, suppose there is a function where y=x from x = 0 to x <=5, y = x sq when 5<x<=7 and y=2x+9 when x>7.
matplotlib plots points, it doesn't care how the points are calculated so the question becomes 'is it possible to write code in Python to populate a list of y values for a domain dependent fuction', and the answer is 'of course'.
e2m2a said:
If so, how would it be done?
Can you post code that plots ##y = 2x + 9##?
 
  • #3
pbuk said:
matplotlib plots points, it doesn't care how the points are calculated so the question becomes 'is it possible to write code in Python to populate a list of y values for a domain dependent fuction', and the answer is 'of course'.

Can you post code that plots ##y = 2x + 9##?
Yes, I can do this. But I can't find any documentation or videos on how to plot a function that changes depending on the domain of x as described above. Would I concatenate the line function or arange function to accomplish this? Not sure how this can be done. Remember I want the whole function plotted as one function on one graph.
 
  • #4
e2m2a said:
Yes, I can do this.
Then please do so and we can show you how to amend it for the DDF you have described.
 
  • #5
e2m2a said:
Is it possible for Python matplotlib to plot in one graph a domain dependent function?
Echoing @pbuk, yes, this is possible.
Here's one that I just did that is similar to what you're trying to do.
Figure_1.png

I fiddled with the formulas to make a continuous graph.
$$f(x) = \begin{cases} x & 0 < x \le 5 \\ -(x - 7)^2 + 9 & 5 < x \le 9 \\ x - 4 & x > 9 \end{cases}$$
I used NumPy linspace() to create separate arrays of x values for the three different domains, and from them created arrays of the corresponding y values. Then it's straightforward to plot the three sets of x and y pairs.
 
  • #6
Fantastic! But can you show me the code how you did this? How did you make this one continuous graph? DId you concatenate the arrays into one array? And then applied the plot function on the one array? Not clear how you did this.
 
Last edited:
  • #7
e2m2a said:
Fantastic! But can you show me the code how you did this? How did you make this one continuous graph? DId you concatenate the arrays into one array? And then applied the plot function on the one array? Not clear how you did this.
There are a number of ways to do this which is why I keep asking you to post the way you would do it for a simple function and then we can show you how to do it for the more complicated one.

Anyway, as we now have one way of doing it here is how I would do it:
Python:
import matplotlib.pyplot as plt
from numpy import linspace

def fn(x):
    if (x <= 0):
        return None
    if (x <= 5):
        return x
    if (x <= 7):
        return x * x
    # x > 7
    return 2 * x + 9

# Create x coordinates.
xList = linspace(-10, 10, 256)
# Calculate y coordinates using a list comprehension.
yList = [fn(x) for x in xList]

plt.plot(xList, yList)
plt.show()
And this is the result:
1643657949774.png

I am not sure if matplotlib can better show the discontinuities.
 
  • Like
Likes Mark44
  • #8
. I was thinking of doing it by creating a function but still was not clear on the details. Thank you for posting this.
 
  • #9
pbuk said:
View attachment 296331
I am not sure if matplotlib can better show the discontinuities.

Probably requires plotting a different series for each domain.

Code:
import numpy as np
import matplotlib.pyplot as plt

xs1 = np.linspace(0,5,11)
f1 = lambda x: x
ys1 = f1(xs1)
xs2 = np.linspace(5,7,5)
f2 = lambda x: x**2
ys2 = f2(xs2)
xs3 = np.linspace(7,10,7)
f3 = lambda x: 2*x+9
ys3 = f3(xs3)

fig = plt.figure()
ax = fig.gca()
# Continuous parts

ax.plot(xs1, ys1, 'k-')
ax.plot(xs2,ys2, 'k-')
ax.plot(xs3,ys3, 'k-')

# End points of domains:
# Open circle if x-value is not included in that domain, filled circle if it is.
ax.plot([5.0, 7.0], [f1(5.0),f2(7.0)], 'ko')
ax.plot([5.0, 7.0], [f2(5.0), f3(7.0)], 
   marker='o', 
   fillstyle='none', 
   markeredgecolor='k', 
   linestyle='none'
)
ax.grid()

plt.show()

Figure_1.png
 
  • Love
  • Like
Likes Mark44 and pbuk
  • #10
pasmith said:
Probably requires plotting a different series for each domain.

Code:
import numpy as np
import matplotlib.pyplot as plt

xs1 = np.linspace(0,5,11)
f1 = lambda x: x
ys1 = f1(xs1)
xs2 = np.linspace(5,7,5)
f2 = lambda x: x**2
ys2 = f2(xs2)
xs3 = np.linspace(7,10,7)
f3 = lambda x: 2*x+9
ys3 = f3(xs3)

fig = plt.figure()
ax = fig.gca()
# Continuous parts

ax.plot(xs1, ys1, 'k-')
ax.plot(xs2,ys2, 'k-')
ax.plot(xs3,ys3, 'k-')

# End points of domains:
# Open circle if x-value is not included in that domain, filled circle if it is.
ax.plot([5.0, 7.0], [f1(5.0),f2(7.0)], 'ko')
ax.plot([5.0, 7.0], [f2(5.0), f3(7.0)],
   marker='o',
   fillstyle='none',
   markeredgecolor='k',
   linestyle='none'
)
ax.grid()

plt.show()

View attachment 296333
That's much better than my amateur effort - glad a professional has arrived!

You can get the discontinuous line all in one series by replacing:
Python:
# Continuous parts

ax.plot(xs1, ys1, 'k-')
ax.plot(xs2,ys2, 'k-')
ax.plot(xs3,ys3, 'k-')
with
Python:
# Concatenate the continuous parts, inserting (x, None) for the discontinuities.
xsAll = np.concatenate((xs1, np.array([5.]), xs2, np.array([7.]), xs3))
ysAll = np.concatenate((ys1, np.array([None]), ys2, np.array([None]), ys3))

ax.plot(xsAll, ysAll, 'k-')
 

Similar threads

Replies
2
Views
3K
Replies
3
Views
2K
Replies
1
Views
1K
Replies
5
Views
2K
Replies
1
Views
769
Replies
2
Views
10K
Replies
21
Views
5K
Back
Top