Computation on Numpy Arrays : Universal Functions

노정훈·2023년 7월 11일
0

Numpy

목록 보기
3/10

Introducing Ufuncs

  • Python's default implementation does some operations very slowly.
  • For many types of operations, Numpy provides a convenient interface into just this kind of statically typed, compiled routine. This is known as a vertorized operation
  • This vectorized approach is designed to push the loop into the compiled layer that underlies Numpy, leading to much faster execution
  • Vectorized operation in Numpy are implemented via ufuncs, whose main purpose is to quickly execute repeated operations on values in Numpy arrays. Ufuncs are extremely flexible.

Exploring Ufuncs

  • Ufuncs exist in two flavors: unary ufuncs, which operate on a single input, and binary ufuncs, which operate on two inputs.

Array Arithmetic

# In[1]
x=np.arange(4)
print("x     =",x)
print("x + 5 =",x+5)
print("x - 5 =",x-5)
print("x * 2 =",x*2)
print("x / 2 =",x/2)
print("x // 2 =",x//2)
# Out[1]
x     = [0 1 2 3]
x + 5 = [5 6 7 8]
x - 5 = [-5 -4 -3 -2]
x * 2 = [0 2 4 6]
x / 2 = [0.  0.5 1.  1.5]
x // 2 = [0 0 1 1]

# In[2]
print("-x     =",-x)
print("x ** 2 =",x**2)
print("x % 2  =",x%2)
# Out[2]
-x     = [ 0 -1 -2 -3]
x ** 2 = [0 1 4 9]
x % 2  = [0 1 0 1]

# In[3]
-(0.5*x + 1) ** 2
# Out[3]
array([-1.  , -2.25, -4.  , -6.25])

Arithmetic operators implemented in Numpy

OperatorEquivalent ufuncDescription
+np.addAddition
-np.subtractSubtraction
-np.negativeUnary negation
*np.multiplyMultiplication
/np.divideDivision
//np.floor_divideFloor division
**np.powerExponentiation
%np.modModulus/remainder

Absolute Value

  • Using np.absolute or np.abs
# In[4]
x=np.array([-2,-1,0,1,2])
print(abs(x))
print(np.absolute(x))
print(abs(x))
# Out[4]
[2 1 0 1 2]
[2 1 0 1 2]
[2 1 0 1 2]

# In[5]
x=np.array([3-4j,4-3j,2+0j,0+1j])
np.abs(x)
# Out[5]
array([5., 5., 2., 1.])

Trigonometric Functions

# In[6]
theta=np.linspace(0,np.pi,3)
print("theta      =",theta)
print("sin(theta) =",np.sin(theta))
print("cos(theta) =",np.cos(theta))
print("tan(theta) =",np.tan(theta))
# Out[6]
theta      = [0.         1.57079633 3.14159265]
sin(theta) = [0.0000000e+00 1.0000000e+00 1.2246468e-16]
cos(theta) = [ 1.000000e+00  6.123234e-17 -1.000000e+00]
tan(theta) = [ 0.00000000e+00  1.63312394e+16 -1.22464680e-16]

# In[7]
x=[-1,0,1]
print("x         =",x)
print("arcsin(x) =",np.arcsin(x))
print("arccos(x) =",np.arccos(x))
print("arctan(x) =",np.arctan(x))
# Out[7]
x         = [-1, 0, 1]
arcsin(x) = [-1.57079633  0.          1.57079633]
arccos(x) = [3.14159265 1.57079633 0.        ]
arctan(x) = [-0.78539816  0.          0.78539816]

Exponents and logarithms

# In[8]
x=[1,2,3]
print("x    =",x)
print("e^x  =",np.exp(x))
print("2^x  =",np.exp2(x))
print("3^x  =",np.power(3,x))
# Out[8]
x    = [1, 2, 3]
e^x  = [ 2.71828183  7.3890561  20.08553692]
2^x  = [2. 4. 8.]
3^x  = [ 3  9 27]

# In[9]
x=[1,2,4,10]
print("x       =",x)
print("ln(x)   =",np.log(x))
print("log2(x) =",np.log2(x))
print("log10(x)=",np.log10(x))
# Out[9]
x       = [1, 2, 4, 10]
ln(x)   = [0.         0.69314718 1.38629436 2.30258509]
log2(x) = [0.         1.         2.         3.32192809]
log10(x)= [0.         0.30103    0.60205999 1.        ]

# In[10]
x=[0,0.001,0.01,0.1]
print("exp(x) - 1 =",np.expm1(x))
print("log(1 + x) =",np.log1p(x))
# Out[10]
exp(x) - 1 = [0.         0.0010005  0.01005017 0.10517092]
log(1 + x) = [0.         0.0009995  0.00995033 0.09531018]

Specialized Ufuncs

  • Another excellent source for more specialized ufuncs is the submodule scipy.special. If you want to compute some obscure mathematical function on your data, chances are it is implemented in scipy.special.
# In[11]
from scipy import special

# In[12]
# Gamma function (generalized factorials) and related functions
x=[1,5,10]
print("gamma(x)     =",special.gamma(x))
print("ln|gamma(x)| =",special.gammaln(x))
print("beta(x,2)    =",special.beta(x,2))
# Out[12]
gamma(x)     = [1.0000e+00 2.4000e+01 3.6288e+05]
ln|gamma(x)| = [ 0.          3.17805383 12.80182748]
beta(x,2)    = [0.5        0.03333333 0.00909091]

# In[13]
# Error function (integral of Gaussian)
x=np.array([0,0.3,0.7,1.0])
print("erf(x)    =",special.erf(x))
print("erfc(x)   =",special.erfc(x))
print("erfinv(X) =",special.erfinv(x))
# Out[13]
erf(x)    = [0.         0.32862676 0.67780119 0.84270079]
erfc(x)   = [1.         0.67137324 0.32219881 0.15729921]
erfinv(X) = [0.         0.27246271 0.73286908        inf]

Advanced Ufuncs Features

Specifying Output

  • In large calculations, it is useful to be able to specify the array where the result of the calculation will be stored.
  • Rather than creating a temporary array, you can use this to write computation results directly to the memory location where you'd like them to be.
  • For all ufuncs, you can do this out argument of the function.
# In[14]
x=np.arange(5)
y=np.empty(5)
np.multiply(x,10,out=y)
print(x)
print(y)
# Out[14]
[0 1 2 3 4]
[ 0. 10. 20. 30. 40.]

# In[15]
y=np.zeros(10)
np.power(2,x,out=y[::2])
print(y)
# Out[15]
[ 1.  0.  2.  0.  4.  0.  8.  0. 16.  0.]

Aggregations

  • reduce method : if we'd like to reduce an array with a particular operation.
# In[16]
x=np.arange(1,6)
print(np.add.reduce(x))
# Out[16]
15

# In[17]
np.multiply.reduce(x)
# Out[17]
120
  • accumulate method : if we'd like to store all the intermediate results of the computation.
# In[18]
np.add.accumulate(x)
# Out[18]
array([ 1,  3,  6, 10, 15])

# In[19]
np.multiply.accumulate(x)
# Out[19]
array([  1,   2,   6,  24, 120])

Outer Products

  • outer method : any ufunc can compute the output of all pairs of two different inputs using this method.
# In[20]
x=np.arange(1,6)
np.multiply.outer(x,x)
# Out[20]
array([[ 1,  2,  3,  4,  5],
       [ 2,  4,  6,  8, 10],
       [ 3,  6,  9, 12, 15],
       [ 4,  8, 12, 16, 20],
       [ 5, 10, 15, 20, 25]])
profile
노정훈

0개의 댓글