Numpy array methods
It is nice with methods that can accept both scalar values (int, float) but also array of values (numpy.ndarray). In many cases I write methods that take only scalar values as arguments, so that I need to itterate this method to work an array of arguments. Here I want to explore the best way to turn these scalar methods into array methods.
#collapse
import numpy as np
import matplotlib.pyplot as plt
import pandas as pd
from scipy.integrate import odeint
Let's pretend that I have developed this method
def scalar_method_1D(x):
condition = (x > 100) # The condition of the if-statement
value_true = 2*x # value of y if condition is True
value_false = x # value of y if condition is False
if condition:
y = value_true
else:
y = value_false
return y
But this method does not work for an array input:
N = 9
x = np.linspace(0,200,N)
try:
y=scalar_method_1D(x=x)
except Exception as e:
print(e)
So in this case we need to do an itteration to get values for an array of x values:
y=[]
for x_ in x:
y_=scalar_method_1D(x=x_)
y.append(y_)
fig,ax=plt.subplots()
ax.plot(x,y,'o')
ax.grid(True)
ax.set_xlabel('x')
ax.set_ylabel('y')
ax.set_title('Itteration solution');
Clearly the if-statement is causing some problems here. The problem can be solved reforumlating the method with np.where(...):
def array_method_1D(x):
condition = (x > 100) # The condition of the if-statement
value_true = 2*x # value of y if condition is True
value_false = x # value of y if condition is False
y = np.where(condition, value_true, value_false)
return y
y=array_method_1D(x=x)
fig,ax=plt.subplots()
ax.plot(x,y,'o')
ax.grid(True)
ax.set_xlabel('x')
ax.set_ylabel('y')
ax.set_title('Itteration solution');
And the array method also works for scalars:
array_method_1D(x=100)
def scalar_method_2D(x,y):
z = x*y
return z
N = 3
x = np.linspace(0,200,N)
y = np.linspace(0,200,N)
scalar_method_2D(x,y)
But it does not work if the arrays don't have the same length:
x = np.linspace(0,200,N)
y = np.linspace(0,200,N+1)
try:
scalar_method_2D(x,y)
except Exception as e:
print(e)
So this one works if x and y have the same length but sometimes you want this method to work if they have different length also. An of course again you can use itteration:
z=np.zeros((len(x),len(y)))
for i,x_ in enumerate(x):
for j,y_ in enumerate(y):
z[i,j] = scalar_method_2D(x_,y_)
z
An alternative solution would be to use np.meshgrid to generate matrixes as input:
X,Y=np.meshgrid(x,y)
Z=scalar_method_2D(X,Y)
Z
But what if there are three arguments: x,y of the same length and z with another one?
x = np.linspace(0,200,N)
y = np.zeros(N)
z = np.linspace(0,200,N+1)
def scalar_method_2D_2(x,y,z):
return (x+y)*z
Itteration solution:
w=np.zeros((len(x),len(z)))
for i,(x_,y_) in enumerate(zip(x,y)):
for j,z_ in enumerate(z):
w[i,j] = scalar_method_2D_2(x_,y_,z_)
w
One way to generete matrixes for this is to use np.tile:
X=np.tile(x,(len(z),1)).transpose()
Y=np.tile(y,(len(z),1)).transpose()
Z=np.tile(z,(len(x),1))
W=scalar_method_2D_2(X,Y,Z)
W