Akima function 'bilinear' is only returning zeros when making interpolations in RStudio

Viewed 68

I'm trying to interpolate data from ERA5 Interim to a finer resolution (from 0.1° to 0.05°). I'm using the bilinear function from the akima package in Rstudio to do so, but whenever I try to compute it I only get zeros. What might be the reason behind this?

As a simplification of my data, I run this line

test_bilinear = bilinear(c(-70.6, -70.5, -70.4, -70.3, -70.2), 
                         c(-34.0, -34.1, -34.2, -34.3, -34.4), 
                         matrix(c(151, 151, 154, 162, 171, 142, 142, 146, 155, 167, 137, 135.09, 141.57, 153.08, 164.60, 139.00, 139.22, 144.59, 154.31, 163.37, 143.13, 144.59, 149.90, 158.23, 164.99), nrow = 5, ncol = 5),
                         c(-70.6, -70.35, -70.65, -71.85), 
                         c(-34.0, -34.05, -34.37, -33.88))[["z"]]

> test_bilinear
[1] 0 0 0 0

But, when I use an example of the bilinear function, it works as intended.

x <- c(0, 2.5, 5, 7.5, 10)
y <- c(50, 55, 60, 65, 70)
z <- matrix(rnorm(25), 5, 5)
x0 <- seq(0, 10, .5)
y0 <- seq(50, 70, length = length(x0))

bilinear(x, y, z, x0, y0)[["z"]]

> bilinear(x, y, z, x0, y0)[["z"]]
 [1] 0.5212130 0.4629981 0.6316416 1.0271434 1.6495036 2.4987221 1.6069258 0.9774763 0.6103738
[10] 0.5056182 0.6632096 0.6206286 0.6874867 0.8637841 1.1495206 1.5446963 0.7932024 0.3964096
[19] 0.3543180 0.6669276 1.3342383

What might be the problem?

1 Answers

The documentation doesn't say this, but apparently akima::bilinear assumes that both x and y are increasing, and that x0 and y0 fall in their range.

In your data, y is c(-34.0, -34.1, -34.2, -34.3, -34.4) which is decreasing. So put it in increasing order, and modify z in a corresponding way.

You'll still have the problem that only the first two of your (x0, y0) points falls in the range of your data. To fix that, you'll need more data, or fewer points to interpolate.

Here are some calculations to illustrate:

# Your original data:

x <- c(-70.6, -70.5, -70.4, -70.3, -70.2) 
y <- c(-34.0, -34.1, -34.2, -34.3, -34.4) 
z <- matrix(c(151, 151, 154, 162, 171, 142, 142, 146, 155, 167, 137, 135.09, 141.57, 153.08, 164.60, 139.00, 139.22, 144.59, 154.31, 163.37, 143.13, 144.59, 149.90, 158.23, 164.99), nrow = 5, ncol = 5)
x0 <- c(-70.6, -70.35, -70.65, -71.85)
y0 <- c(-34.0, -34.05, -34.37, -33.88)

library(akima)

# Completely bad results:
bilinear(x, y, z, x0, y0)
#> $x
#> [1] -70.60 -70.35 -70.65 -71.85
#> 
#> $y
#> [1] -34.00 -34.05 -34.37 -33.88
#> 
#> $z
#> [1] 0 0 0 0

# Fix y and z:
y <- rev(y)
z <- z[, 5:1]
bilinear(x, y, z, x0, y0)
#> $x
#> [1] -70.60 -70.35 -70.65 -71.85
#> 
#> $y
#> [1] -34.00 -34.05 -34.37 -33.88
#> 
#> $z
#> [1] 151.00 154.25   0.00   0.00

x0 < min(x)
#> [1] FALSE FALSE  TRUE  TRUE

Created on 2022-02-08 by the reprex package (v2.0.1.9000)

We now have some reasonable interplated values for the 1st two points, but not the last two. But look at x0 < min(x): it is TRUE for the last two points. They are out of range.

Related