Functions of Arrays

This notebook illustrates how to apply a function to arrays. Another notebook focuses on matrix algebra.

Load Packages and Extra Functions


In [1]:
using Dates, Printf

include("printmat.jl")   #a function for prettier matrix printing


Out[1]:
printwhere (generic function with 1 method)

Elementwise Functions of Arrays: Using Dot (.)

Let X be an array, and a and b be scalars. Then, y = fn.(X,a,b) generates an array y where y[i,j] = fn(X[i,j],a,b)

(You could achieve the same thing with map(xi->fn(xi,a,b),x).)


In [2]:
fn(x,a,b) = a/x + b             #x has to be a scalar for this to work


Out[2]:
fn (generic function with 1 method)

In [3]:
X = [1 2;
     0 10]

printmat(fn.(X,100,10))         #notice the dot.


   110.000    60.000
       Inf    20.000

Looping over Columns or Rows

Suppose you want to calculate the sum of each row of a matrix. The classical way of doing that is to loop.

Notice that instead of sum(x[:,i]) it may be faster and save memory to do sum(view(X,i,:)) because this avoids creating a new array of x[:,i].


In [4]:
X = [1 2;
     0 10]
println("X:")
printmat(X)

m = size(X,1)

z = fill(0,m)                  #to fill with results
for i = 1:m                    #loop over rows
    z[i] = sum(X[i,:])         #or sum(view(X,i,:)) to save memory
end

println("sum of each row:")
printmat(z)


X:
         1         2
         0        10

sum of each row:
         3
        10

Functions with Built-in dims Argument

May functions have a dims argument that allows you to avoid looping, for instance, sum.


In [5]:
printmat(sum(X,dims=2))


         3
        10

Functions with Built-in function and dims Arguments (extra)

Several functions allow you to also apply an elementwise function to X before doing the rest of the calculations, for instance, any, all, sum, prod, maximum, and minimum.


In [6]:
sum(abs2,X,dims=2)           #same as sum(abs2.(X),dims=2) but faster


Out[6]:
2×1 Array{Int64,2}:
   5
 100

Apply Your Own Function on Each Column: mapslices (extra)

...or each row (or some other dimension)

The mapslices(fun,x,dims=1) applies fun(x[:,i]) to each column of a matrix x. This is an alternative to looping over the columns.

The cell below illustrates this by calling a function which calculates the moving average of x[t] and x[t-1] for each column of a matrix X.


In [7]:
function MovingAvg2(x)             #moving average of t and t-1
    T = length(x)
    y = fill(NaN,T) 
    for t = 2:T
        y[t] = (x[t] + x[t-1])/2
    end
    return y
end

X = [1:5 101:105]
Y = mapslices(MovingAvg2,X,dims=1)
println("      X (with 2 columns) and Y (MA(1) of X):")
printmat([X Y])


      X (with 2 columns) and Y (MA(1) of X):
     1.000   101.000       NaN       NaN
     2.000   102.000     1.500   101.500
     3.000   103.000     2.500   102.500
     4.000   104.000     3.500   103.500
     5.000   105.000     4.500   104.500


In [ ]: