2

I would like to graph a custom function including min and max :

import numpy as np
import matplotlib.pyplot as plt

f = lambda x: max(0, x)
x = np.linspace(-10, 10)
y = f(x)

plt.plot(x, y)
plt.show()

Result:

ValueError: The truth value of an array with more than one element is ambiguous. Use a.any() or a.all()

Some help will be welcome

1

4 Answers 4

4

use vectorized np.clip() instead of f - this way you can set both lower (a_min) and upper (a_max) boundaries in one step:

y = np.clip(x, a_min=0, a_max=None)

or try to vectorize your scalar funcion:

In [146]: x = np.linspace(-1000, 1000, 10**6)

In [147]: x.shape
Out[147]: (1000000,)

In [148]: vf = np.vectorize(f)

In [149]: %timeit [f(i) for i in x]
1.46 s ± 5.42 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)

In [150]: %timeit vf(x)
1.03 s ± 8.73 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)
Sign up to request clarification or add additional context in comments.

4 Comments

Undoubtedly faster than my list comp for big problems, but it's an optimisation specific to this particular problem, not a general lambda.
Thank you, my final custom function is not only based on min/max, it contains min/max
@alex, i'd suggest you to post your function - if it can be vectorized in a way that it uses fast (vectorized) ufuncs - it might be much faster compared to list comprehension approach...
@roganjosh, list comprehension might be faster for small arrays ;-)
4

Instead of max, use np.maximum:

from matplotlib import pyplot as plt
import numpy as np

f = lambda x: np.maximum(0, x)
x = np.linspace(-10,10)
y = f(x)

plt.plot(x,y)
plt.show()

EDIT:

In case of more complex functions, look out for the numpy equivalents of the functions you intend to use. Most of the time the names are the same as in the math module, e.g. math.sin would become np.sin etc. However, as in the example, max should be replaced by np.maximum not np.max, the latter of which returns the maximum value of an np.ndarray.

5 Comments

This is the most elegant, IMO, solution to the particular problem but the question is "Graph a custom function in python" and this just addresses the single case that was given by the OP.
@roganjosh Quite true, but on the other hand, numpy provides a lot of vectorised versions of mathematical functions. At least all the functions in math are also defined in numpy, so this example can easily be extended.
The idea would of course be to replace all the max from the function by np.maximum. Interestingly np.clip seems to be a little faster than np.maximum. Using np.vectorize on the initial function is 100 times slower than any of the numpy functions.
@ImportanceOfBeingErnest could it be that np.maximum and np.minimum are implemented using np.clip? That would explain the better performance.
I have no idea. By far the fastest solution would be to compare inplace, def f(x): x[x<=0] = 0; return x
2

You could just use a list comprehension to get the corresponding y value for every value of x.

import numpy as np
import matplotlib.pyplot as plt

f = lambda x: max(0, x)
x = np.linspace(-10, 10)
y = [f(i) for i in x]

plt.plot(x, y)
plt.show()

Comments

2

I found it useful to define one function that can be called using one line of code, so now I can plot any function (assuming the invoked components are valid, e.g. log is loaded as "from math import log", or is expressed as "math.log", and that the function can be evaluated over the specified range):

import matplotlib.pyplot as plt   #; plt.rcdefaults()
import numpy as np
from math import log

def plot_func(x,f):
  # x = tuple defining range of x
  # f = string defining function to plot, in terms of x
  x = np.linspace(x[0],x[1],201)
  y = list(map(lambda x: eval(f), x))
  plt.close()
  plt.title('f(x) = ' + f)
  plt.plot(x,y, 'b')

plot_func(x=(0, 1), f = '60 * (x**3) * (1-x)**2') 

Generates:

enter image description here

It's just nice to avoid formal definition of the function being plotted, and to be able to reuse this to plot anything with one simple line to be tweaked.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.