Home > database >  Conditional slicing in a 2-dimensional array in R
Conditional slicing in a 2-dimensional array in R

Time:11-02

I have a two-dimension array made up from latitude(dimension 1) and longitude(dimension 2) coordinates. The position of each pair of lat,long coordinates corresponds to a position in a 3-dimensional array of temperature data (Third dimension representing depth).

I would like to extract the positions of lat long coordinates such that the latitude is valued 60<lat<70 and -60<long<-50 so that I can relate them to the temperature array and extract temperature data for particular regions. I am new to R, and programming in general, so this has been quite the problem for me.

#Extracts latitude and longitude matrices into variables
nav_lat <- ncvar_get(nc,"nav_lat")
nav_long <- ncvar_get(nc,"nav_lon")

#Overlays lat and long matrices to create pairs
nav_latlong <- array(c(nav_lat,nav_long),dim=(c(1442,398,2)))

region <- filter(nav_latlong,between(60,70) & between(-60,-50))

Is this what you mean by a small reproducible example?:

library(tidyverse)

vector_1 <- c(5,9,3)
vector_2 <- c(10,11,12)
result <- array(c(vector_1,vector_2),dim=c(3,3,2))

region <- filter(result,between(result[,,1],5,10) & between(result[,,2],10,12))

SO here I would want to extract pairs where the first element is between 5 and 10, and the second element is between 10 and 12.

CodePudding user response:

Here is another option:

#example
set.seed(1)
lat <- matrix(runif(9, 50, 80), nrow = 3)
long <- matrix(runif(9, -70, -50), nrow = 3)
latlong <- array(c(lat, long), dim = c(3,3,2))

latlong
#> , , 1
#> 
#>          [,1]     [,2]     [,3]
#> [1,] 57.96526 77.24623 78.34026
#> [2,] 61.16372 56.05046 69.82393
#> [3,] 67.18560 76.95169 68.87342
#> 
#> , , 2
#> 
#>           [,1]      [,2]      [,3]
#> [1,] -68.76427 -56.25954 -60.04602
#> [2,] -65.88051 -62.31793 -55.64763
#> [3,] -66.46886 -54.60317 -50.16188


#create filter mask
mask <- array(dim = c(3,3,2))
mask[,,1] <- dplyr::between(latlong[,,1], 60, 70)
mask[,,2] <- dplyr::between(latlong[,,2], -60, -50)
mask <- mask[,,1] & mask[,,2]
mask
#>       [,1]  [,2]  [,3]
#> [1,] FALSE FALSE FALSE
#> [2,] FALSE FALSE  TRUE
#> [3,] FALSE FALSE  TRUE

#apply mask to get lat long pairs
apply(latlong, 3, \(x) x[mask])
#>          [,1]      [,2]
#> [1,] 69.82393 -55.64763
#> [2,] 68.87342 -50.16188

Edit extract temperatures

If you want to know the indexes for the lat long in the original array, you can use which(mask, arr.ind = TRUE). You don't need mask == TRUE because mask is already logical (i.e., matrix of TRUE and FALSE). Alternatively, you can just apply the mask to your temperature matrix (assuming it is the same dimensions). see below.

#temperature example
set.seed(32)
temperatures <- matrix(runif(9, -20, 20), nrow = 3)
temperatures
#>            [,1]       [,2]      [,3]
#> [1,]  0.2336209   9.152789 10.141508
#> [2,]  3.7923355 -13.920497 14.082492
#> [3,] 12.3498853  18.247490  6.937671

#get the temperatures
temperatures[mask]
#> [1] 14.082492  6.937671

Or even better would be to add the temperatures to the lat long array and extract everything at once, so that you have a nice data output:

all_data <- abind::abind(latlong, temperatures, along = 3)
all_data
#> , , 1
#> 
#>          [,1]     [,2]     [,3]
#> [1,] 57.96526 77.24623 78.34026
#> [2,] 61.16372 56.05046 69.82393
#> [3,] 67.18560 76.95169 68.87342
#> 
#> , , 2
#> 
#>           [,1]      [,2]      [,3]
#> [1,] -68.76427 -56.25954 -60.04602
#> [2,] -65.88051 -62.31793 -55.64763
#> [3,] -66.46886 -54.60317 -50.16188
#> 
#> , , 3
#> 
#>            [,1]       [,2]      [,3]
#> [1,]  0.2336209   9.152789 10.141508
#> [2,]  3.7923355 -13.920497 14.082492
#> [3,] 12.3498853  18.247490  6.937671

#get lat long and temperature
apply(all_data, 3, \(x) x[mask]) |>
  `colnames<-`(c("Lat", "Long", "Temperature"))
#>           Lat      Long Temperature
#> [1,] 69.82393 -55.64763   14.082492
#> [2,] 68.87342 -50.16188    6.937671
  • Related