Search code examples
rrasterr-spterra

Convert large list with different lat/lon lengths to raster and/or simple data frame


I'm trying to work with a dataset of global sea surface salinity values that are conveniently provided in the packages oce and ocedata.

The issue is that I want more custom control over data aesthetics and the data arrive in a very weird structure: a large list with 4 elements of different lengths. It seems clear to me that lat and long values are different lengths, simple enough, but I cannot get the object reworked into a simple data frame (or raster object, that'd be fine too). I really do not want to use the canned function for plotting that these packages provide and instead want a straightforward dataframe (for ggplot).

Here are the data and their version of the plot:

install.packages(oce); install.packages(ocedata)

data(levitus, package="ocedata")

oce::imagep(levitus$longitude, levitus$latitude, levitus$SSS)

How can I convert the levitcus (sea surface salinity) data into a simple data frame with z values and xy coordinates?


Solution

  • You can use expand.grid to get appropriate repetitions of the longitude and latitude - these will match the values of SSS when it is converted to a vector:

    data(levitus, package="ocedata")
    
    df <- cbind(expand.grid(x = levitus$longitude, y = levitus$latitude), 
                z = c(levitus$SSS))
    
    df <- df[complete.cases(df),]
    
    head(df)
    #>           x     y        z
    #> 4322 -178.5 -77.5 34.23599
    #> 4323 -177.5 -77.5 34.21039
    #> 4324 -176.5 -77.5 34.18909
    #> 4325 -175.5 -77.5 34.16771
    #> 4326 -174.5 -77.5 34.15121
    #> 4327 -173.5 -77.5 34.13439
    

    We can confirm this is correct by using ggplot to draw the resulting data frame in terms of x, y and z (for color)

    library(ggplot2)
    
    ggplot(df, aes(x, y, fill = z)) + geom_raster() + scale_fill_viridis_c()
    

    Created on 2022-06-15 by the reprex package (v2.0.1)