[R] [newbie] convert 3D spatial array to dataframe

Tom Roche Tom_Roche at pobox.com
Sun Nov 18 05:36:47 CET 2012


summary: how to convert a 3D array (as obtained from ncdf4::ncvar_get)
to a dataframe suitable for use by lattice::levelplot(), e.g.,

levelplot(conc ~ lon * lat | lev, data = data.frame)

details:

I have atmospheric data in netCDF files specifying gas concentrations
over a 3D space with dimensions longitude, latitude, and (vertical)
level. I need to plot the data by level. Since there are several levels,
I'm guessing I should use package=lattice, which I have not previously
used. (I have used package=fields, and I would like to plot the levels
over a map, but lattice seems to provide the best way to organize
multiple plots--please correct me if wrong.)

>From reading Sarkar's excellent lattice book

http://dx.doi.org/10.1007/978-0-387-75969-2

it seems that one best provides data to lattice::levelplot() via
dataframe, since the dataframe provides a sort of namespace for the
trellis "formula." I know that ncdf4::ncvar_get will return my
concentrations as the values in a 3D array with dimensions={lon, lat,
lev} so I'm trying to find a way to convert a 3D array to a dataframe.
Here's my small, self-contained example:

lon=11
lat=7
lev=5
len=lon*lat*lev
array.3d <- array(data=c(1:len), dim=c(lat, lon, lev))

# Rewrite the array values "more spatially," i.e., row-wise from
# bottom left. If there's a more-R-ish way to fill this array
# as specified, please let me know: I know 'for' loops are deprecated
# in R.

i=1
for (z in 1:lev) {
  for (x in lat:1) {
    for (y in 1:lon) {
      array.3d[x,y,z]=i ; i=i+1
    }
  }
}

produces (with rows=latitudes and cols=longitudes)

> array.3d[,,1]
     [,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8] [,9] [,10] [,11]
[1,]   67   68   69   70   71   72   73   74   75    76    77
[2,]   56   57   58   59   60   61   62   63   64    65    66
[3,]   45   46   47   48   49   50   51   52   53    54    55
[4,]   34   35   36   37   38   39   40   41   42    43    44
[5,]   23   24   25   26   27   28   29   30   31    32    33
[6,]   12   13   14   15   16   17   18   19   20    21    22
[7,]    1    2    3    4    5    6    7    8    9    10    11
> array.3d[,,lev]
     [,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8] [,9] [,10] [,11]
[1,]  375  376  377  378  379  380  381  382  383   384   385
[2,]  364  365  366  367  368  369  370  371  372   373   374
[3,]  353  354  355  356  357  358  359  360  361   362   363
[4,]  342  343  344  345  346  347  348  349  350   351   352
[5,]  331  332  333  334  335  336  337  338  339   340   341
[6,]  320  321  322  323  324  325  326  327  328   329   330
[7,]  309  310  311  312  313  314  315  316  317   318   319

I want to convert array.3d to a dataframe with structure like the
following (note order of data values is arbitrary):

lon  lat  lev  conc
---  ---  ---  ----
  1    7    1     1
  2    7    1     2
  3    7    1     3
...
  9    1    1    75
 10    1    1    76
 11    1    1    77
...
  9    1    5   383
 10    1    5   384
 11    1    5   385

How to do that? I'm guessing this involves function=reshape, but I can't
see how to make `reshape` work for this usecase.

TIA, Tom Roche <Tom_Roche at pobox.com>



More information about the R-help mailing list