This question already has answers here:
Problem passing boolean array results iterativly into if statement - new to python
(1 answer)
Why applying a conditional expression doesn't work on numpy array
(1 answer)
plotting a function defined piecewise with matplotlib in python
(1 answer)
Create a function with an if statement inside
(1 answer)
Closed last month.
I'm trying to plot a function whose output f(x) depends on floor(x)%3. However, when I tried plotting it using matplotlib, I got this error:
ValueError: The truth value of an array with more than one element is ambiguous. Use a.any() or a.all()
I understand that it's because x is an array and so floor(x)%3 doesn't really mean anything. However, is there a way to make python treat x like a single number and not an array?
Here is the code:
from matplotlib import pyplot as plt
plt.rcParams["figure.figsize"] = [7.50, 3.50]
plt.rcParams["figure.autolayout"] = True
def f(x):
if np.floor(x / 3) % 3 == 1:
return -x + 2 + 4 * np.floor(x/3)
elif np.floor(x / 3) % 3 == 2:
return x - 2 * np.floor((x + 1) / 3)
elif np.floor(x / 3) % 3 == 0:
return x - 2 * np.floor(x / 3)
x = np.linspace(-10, 10, 100)
plt.plot(x, f(x), color='blue')
plt.show()
Any help will be appreciated, thanks in advance!
Related
I wish to locate the index of the closest higher value to a query over a sorted numpy array (where the query value is not in the array).
similar to bisect_right in the python standard library, without converting the numpy array to a python list, and leveraging the fact that the array is sorted (i.e. runtime should be O(log N), like numpy's searchsorted).
Pandas have this option using get_loc with the 'bfill' option, but it seems a bit of an overkill to include it as a dependency just for this... I might have to resort to holding this array as both a python list and a numpy array, but wanted to hear if there's a more reasonable solution.
Edit: It seems searchsorted does exactly what I need.
We can see the code for bisect_right on github:
def bisect_right(a, x, lo=0, hi=None):
"""Return the index where to insert item x in list a, assuming a is sorted.
The return value i is such that all e in a[:i] have e <= x, and all e in
a[i:] have e > x. So if x already appears in the list, a.insert(x) will
insert just after the rightmost x already there.
Optional args lo (default 0) and hi (default len(a)) bound the
slice of a to be searched.
"""
if lo < 0:
raise ValueError('lo must be non-negative')
if hi is None:
hi = len(a)
while lo < hi:
mid = (lo+hi)//2
# Use __lt__ to match the logic in list.sort() and in heapq
if x < a[mid]: hi = mid
else: lo = mid+1
return lo
This is all numpy compliant:
import numpy as np
array = np.array([1,2,3,4,5,6])
print(bisect_right(array, 7))
>>> 6
print(bisect_right(array, 0))
>>> 0
To find the index of the closest higher value to a number given:
def closest_higher_value(array, value):
if bisect_right(array, value) < len(array):
return bisect_right(array, value)
print("value too large:", value, "is bigger than all elements of:")
print(array)
print(closest_higher_value(array, 3))
>>> 3
print(closest_higher_value(array, 7))
>>> value too large: 7 is bigger than all elements of:
>>> [1 2 3 4 5 6]
>>> None
I am trying to store all columns of a numpy array in a variable by using a for loop (python 2). However, there is either a syntax error or I am required to define x.
This is what I have tried.
1)
x for x in train[:,x]:
if x not in [target, IDcol]:
predictors= x
2)
predictors = [x for x in train[:,x] if x not in [target, IDcol]]
This code can't work.
Because you use x like a new variable but you already use it in train[:,x] !
Change your variables :
predictors = [x2 for x2 in train[:,x] if x2 not in [target, IDcol]]
This question already has answers here:
Populate numpy matrix from the difference of two vectors
(2 answers)
Closed 5 years ago.
Is there a fast numpy way of quickly doing the following:
x = np.array([0,1,2,3,4]) # a
y = np.array([10,20])
# x - y = np.array([[10, 20],[9,19],[8,18],[7,17],[6,16]]) # 5x2 matrix
Where the result would be the absolute difference between each element in x minus each element in y
Yes there is, its down to how you build your array containing the result...
import numpy as np
x = np.array([0,1,2,3,4])
y = np.array([10,20])
z = np.array([y[0]-x[:], y[1]-x[:]])
zT = np.transpose(z)
I have an equation dy/dx = x + y/5 and an initial value, y(0) = -3.
I would like to know how to plot the exact graph of this function using pyplot.
I also have a x = np.linspace(0, interval, steps+1) which I would like to use as the x axis. So I'm only looking for the y axis values.
Thanks in advance.
Just for completeness, this kind of equation can easily be integrated numerically, using scipy.integrate.odeint.
import numpy as np
from scipy.integrate import odeint
import matplotlib.pyplot as plt
# function dy/dx = x + y/5.
func = lambda y,x : x + y/5.
# Initial condition
y0 = -3 # at x=0
# values at which to compute the solution (needs to start at x=0)
x = np.linspace(0, 4, 101)
# solution
y = odeint(func, y0, x)
# plot the solution, note that y is a column vector
plt.plot(x, y[:,0])
plt.xlabel('x')
plt.ylabel('y')
plt.show()
Given that you need to solve the d.e. you might prefer doing this algebraically, with sympy. (Or you might not.)
Import the module and define the function and the dependent variable.
>>> from sympy import *
>>> f = Function('f')
>>> var('x')
x
Invoke the solver. Note that all terms of the d.e. must be transposed to the left of the equals sign, and that the y must be replaced by the designator for the function.
>>> dsolve(Derivative(f(x),x)-x-f(x)/5)
Eq(f(x), (C1 + 5*(-x - 5)*exp(-x/5))*exp(x/5))
As you would expect, the solution is given in terms of an arbitrary constant. We must solve for that using the initial value. We define it as a sympy variable.
>>> var('C1')
C1
Now we create an expression to represent this arbitrary constant as the left side of an equation that we can solve. We replace f(0) with its value in the initial condition. Then we substitute the value of x in that condition to get an equation in C1.
>>> expr = -3 - ( (C1 + 5*(-x - 5)*exp(-x/5))*exp(x/5) )
>>> expr.subs(x,0)
-C1 + 22
In other words, C1 = 22. Finally, we can use this value to obtain the particular solution of the differential equation.
>>> ((C1 + 5*(-x - 5)*exp(-x/5))*exp(x/5)).subs(C1,22)
((-5*x - 25)*exp(-x/5) + 22)*exp(x/5)
Because I'm absentminded and ever fearful of making egregious mistakes I check that this function satisfies the initial condition.
>>> (((-5*x - 25)*exp(-x/5) + 22)*exp(x/5)).subs(x,0)
-3
(Usually things are incorrect only when I forget to check them. Such is life.)
And I can plot this in sympy too.
>>> plot(((-5*x - 25)*exp(-x/5) + 22)*exp(x/5),(x,-1,5))
<sympy.plotting.plot.Plot object at 0x0000000008C2F780>
In sympy 0.7.6, I had no troubles with the following code for both the modules='sympy' and the modules='numpy' options. Now with sympy v0.1, the evaluation with modules='numpy' raise a ZeroDivisionError:
import sympy
x, y = sympy.symbols(['x', 'y'])
expr = sympy.Piecewise((1/x, y < -1), (x, y <= 1), (1/x, True))
f_sympy = sympy.lambdify([x, y], expr, modules='sympy')
f_numpy = sympy.lambdify([x, y], expr, modules='numpy')
print f_sympy(0, 1) # performs well
print f_numpy(0, 1) # issue: ZeroDivisionError
Seems like the piecewise functions evaluate before the condition with modules='numpy'.
My questions are:
Is this behavior normal?
If so, why, and how to define a piecewise expression and evaluate it as fast as with numpy module without the sympy.lambdify procedure?
EDIT:
Found that in my case the solution is theano:
import sympy
x, y = sympy.symbols(['x', 'y'])
f = sympy.Piecewise((1/x, y < -1), (x, y <= 1), (1/x, True))
from sympy.printing.theanocode import theano_function
f_theano = theano_function([x, y], [f])
print f_theano(0, 1) # OK, return 0
I deleted my other answer (in case you already saw it). There is a much simpler solution.
The ZeroDivisionError comes because the lambdified expression produces, roughly, lambda x, y: select([less(y, -1),less_equal(y, 1),True], [1/x,x,1/x], default=nan). The problem is that passing in x = 0 results in 1/0 being evaluated by Python, which raises the error.
But NumPy is just fine with dividing by zero. It will issue a warning, but otherwise works fine (it gives inf), and in this example there is no problem, because the inf is not actually used.
So the solution is to wrap the input to lambdify as numpy arrays, that is, instead of
f_numpy(0, 1)
use
f_numpy(array(0), array(1))
There is a SymPy issue discussing this if you are interested.