# Array Transformations

Earth Engine supports array transformations such as transpose, inverse and pseudo-inverse. As an example, consider an ordinary least squares (OLS) regression of a time series of images. In the following example, an image with bands for predictors and a response is converted to an array image, then “solved” to obtain least squares coefficients estimates three ways. First, assemble the image data and convert to arrays:

### Code Editor (JavaScript)

```// This function masks the input with a threshold on the simple cloud score.
var cloudscore = ee.Algorithms.Landsat.simpleCloudScore(img).select('cloud');
};

// Load a Landsat 5 image collection.
var collection = ee.ImageCollection('LANDSAT/LT05/C01/T1_TOA')
// Filter to get only two years of data.
.filterDate('2008-04-01', '2010-04-01')
// Filter to get only imagery at a point of interest.
.filterBounds(ee.Geometry.Point(-122.2627, 37.8735))
// Select NIR and red bands only.
.select(['B4', 'B3'])
// Sort the collection in chronological order.
.sort('system:time_start', true);

// This function computes the predictors and the response from the input.
var makeVariables = function(image) {
// Compute time of the image in fractional years relative to the Epoch.
var year = ee.Image(image.date().difference(ee.Date('1970-01-01'), 'year'));
// Compute the season in radians, one cycle per year.
var season = year.multiply(2 * Math.PI);
// Return an image of the predictors followed by the response.
return image.select()
.toFloat();
};

// Define the axes of variation in the collection array.
var imageAxis = 0;
var bandAxis = 1;

// Convert the collection to an array.
var array = collection.map(makeVariables).toArray();

// Check the length of the image axis (number of images).
var arrayLength = array.arrayLength(imageAxis);
// Update the mask to ensure that the number of images is greater than or
// equal to the number of predictors (the linear model is solveable).

// Get slices of the array according to positions along the band axis.
var predictors = array.arraySlice(bandAxis, 0, 4);
var response = array.arraySlice(bandAxis, 4);```

Note that `arraySlice()` returns all the images in the time series for the range of indices specified along the `bandAxis` (the 1-axis). At this point, matrix algebra can be used to solve for the OLS coefficients:

### Code Editor (JavaScript)

```// Compute coefficients the hard way.
var coefficients1 = predictors.arrayTranspose().matrixMultiply(predictors)
.matrixInverse().matrixMultiply(predictors.arrayTranspose())
.matrixMultiply(response);```

Although this method works, it is inefficient and makes for difficult to read code. A better way is to use the `pseudoInverse()` method (`matrixPseudoInverse()` for an array image):

### Code Editor (JavaScript)

```// Compute coefficients the easy way.
var coefficients2 = predictors.matrixPseudoInverse()
.matrixMultiply(response);```

From a readability and computational efficiency perspective, the best way to get the OLS coefficients is `solve()` (`matrixSolve()` for an array image). The `solve()` function determines how to best solve the system from characteristics of the inputs, using the pseudo-inverse for overdetermined systems, the inverse for square matrices and special techniques for nearly singular matrices:

### Code Editor (JavaScript)

```// Compute coefficients the easiest way.
var coefficients3 = predictors.matrixSolve(response);```

To get a multi-band image, project the array image into a lower dimensional space, then flatten it:

### Code Editor (JavaScript)

```// Turn the results into a multi-band image.
var coefficientsImage = coefficients3
// Get rid of the extra dimensions.
.arrayProject()
.arrayFlatten([
['constant', 'trend', 'sin', 'cos']
]);```

Examine the outputs of the three methods and observe that the resultant matrix of coefficients is the same regardless of the solver. That `solve()` is flexible and efficient makes it a good choice for general purpose linear modeling.

[{ "type": "thumb-down", "id": "missingTheInformationINeed", "label":"Missing the information I need" },{ "type": "thumb-down", "id": "tooComplicatedTooManySteps", "label":"Too complicated / too many steps" },{ "type": "thumb-down", "id": "outOfDate", "label":"Out of date" },{ "type": "thumb-down", "id": "samplesCodeIssue", "label":"Samples / code issue" },{ "type": "thumb-down", "id": "otherDown", "label":"Other" }]
[{ "type": "thumb-up", "id": "easyToUnderstand", "label":"Easy to understand" },{ "type": "thumb-up", "id": "solvedMyProblem", "label":"Solved my problem" },{ "type": "thumb-up", "id": "otherUp", "label":"Other" }]