How to Create a Raster from a Data Frame in R

How to create a raster from a data frame in r?

Here is one approach, via SpatialPixelsDataFrame

library(raster)
# create spatial points data frame
spg <- df
coordinates(spg) <- ~ x + y
# coerce to SpatialPixelsDataFrame
gridded(spg) <- TRUE
# coerce to raster
rasterDF <- raster(spg)
rasterDF
# class : RasterLayer
# dimensions : 2, 2, 4 (nrow, ncol, ncell)
# resolution : 1, 1 (x, y)
# extent : -0.5, 1.5, -0.5, 1.5 (xmin, xmax, ymin, ymax)
# coord. ref. : NA
# data source : in memory
# names : l
# values : -0.6674423, 1.360611 (min, max)

help('raster') describes a number of methods to create a raster from objects of different classes.

How to make data frame into raster object R

Pretty much like in most examples that come with the raster package.

b1DF <- data.frame(b1 = c(18880, 19364, 20446, 21070, 23001, 22981, 23362,
19538,18902, 19013, 18676, 20998, 23206, 24784, 21979, 20804, 20496, 19993,
20830, 22396, 24246, 19877, 21002, 21771, 21478, 20827, 21267, 23036, 20103,
21220, 22308, 21443, 20780, 21874, 23029, 19521, 20173, 20826, 21000, 21693,
23388, 23935))

library(raster)
r <- raster(nrow=6, ncol=7, ext=extent(286695, 286905, 4620945, 4621125), crs="+proj=utm +zone=17 +datum=WGS84 +units=m")
values(r) <- b1DF$b1

r
#class : RasterLayer
#dimensions : 6, 7, 42 (nrow, ncol, ncell)
#resolution : 30, 30 (x, y)
#extent : 286695, 286905, 4620945, 4621125 (xmin, xmax, ymin, ymax)
#crs : +proj=utm +zone=17 +datum=WGS84 +units=m +ellps=WGS84 +towgs84=0,0,0
#source : memory
#names : layer
#values : 18676, 24784 (min, max)

How To convert dataframe to raster::stack object?

You can use

r = stack(lapply(df, function(j) raster(matrix(j, nrow=5))))

# class : RasterStack
# dimensions : 5, 4, 20, 6 (nrow, ncol, ncell, nlayers)
# resolution : 0.25, 0.2 (x, y)
# extent : 0, 1, 0, 1 (xmin, xmax, ymin, ymax)
# crs : NA
# names : SST, SSS, SO2, NPP, MLD, SIC
# min values : 7.591805e+00, 3.404505e+01, 2.537586e-01, 3.851564e-07, 5.871885e+01, 0.000000e+00
# max values : 1.587188e+01, 3.506759e+01, 2.998243e-01, 6.431131e-07, 1.086455e+02, 0.000000e+00

You did not specify the dimensions of the raster layers, so in the above, I assumed 5 rows. You will need to specify this dimension to suit your data, as it cannot be inferred directly from the data.

Transform raster data to data.frame

You are going about this very much the wrong way. You should not use @. For example, instead of rgb@layers use nlayers(rgb). Also, you should never use assign.

Example data

library(raster)
rgb <- brick(nc=10, nr=10, nl=3)
set.seed(1)
rgb <- setValues(rgb, round(runif(3 * ncell(r)) * 255))
names(rgb) <- c("R", "G", "B")

You do not need that loop at all. You can just do

v <- as.data.frame(rgb)
head(v)
R G B
1 68 167 68
2 95 90 56
3 146 69 132
4 232 253 69
5 51 162 46
6 229 54 132

Or

v <- data.frame(values(rgb))

You could that with a loop. The easiest way would be to use a list

x <- list()
for (i in 1:nlayers(rgb)){
x[[i]] <- values(rgb[[i]])
}

df <- data.frame(x)
colnames(df) <- names(rgb)

Plotting points extracted from a dataframe in a Raster layer

1. Please find below a reprex providing a possible solution using raster and sf libraries.

library(raster)
library(sf)

# Create from scratch the raster with 0 values
raster0 <- raster(nrows = 44, ncols = 41,
xmn = -133.2625, xmx = -121.3042,
ymn = 41.3875, ymx = 54.22083,
vals=0)

# Convert points 'sf' object into 'sp' object
points_sp <- as(points, "Spatial")

# Extract the cells of raster0 matching the points geometry of the 'sp' object
cells_ID <- extract(raster0, points_sp, cellnumbers=TRUE)[,"cells"]

# Copy raster0 (as you want the final result in another raster)
raster01 <- raster0

# Replace 0 values to 1 for cells matching points geometry in the 'raster01'
raster01[cells_ID] <- 1

# Visualization of the final result
plot(raster01)

Created on 2021-12-07 by the reprex package (v2.0.1)


2. Please find below a reprex providing another solution using terra and sf libraries

library(terra)
library(sf)

# Create from scratch the 'SpatRaster' with 0 values
raster0 <- rast(nrows=44, ncols=41,
nlyrs=1,
xmin=-133.2625, xmax=-121.3042,
ymin=41.3875, ymax=54.22083,
vals = 0)

# Convert points 'sf' object into 'SpatVector' object
points <- vect(points)

# Extract the cells of raster0 matching the points geometry of the 'sp' object
cells_ID <- terra::extract(raster0, points, cells = TRUE)

# Copy raster0 (as you want the final result in another raster)
raster01 <- raster0

# Replace 0 values to 1 for cells matching points geometry in the 'raster01'
raster01[cells_ID[,"cell"]] <- 1

# Visualization of the final result
plot(raster01)

Created on 2021-12-07 by the reprex package (v2.0.1)

R: Create raster object from a dataframe with min and max values for x and y coordinates of raster cells

How about something like this...

when df is your dataframe with the minimum and maximum values:

       xmin      ymin      ymax      xmax
1 -73.99139 -18.04158 -17.04158 -72.99139
2 -72.99139 -18.04158 -17.04158 -71.99139
3 -71.99139 -18.04158 -17.04158 -70.99139
4 -70.99139 -18.04158 -17.04158 -69.99139
5 -69.99139 -18.04158 -17.04158 -68.99139
6 -68.99139 -18.04158 -17.04158 -67.99139

#calculate point center
xcoords <- (df[,"xmax"] - df[,"xmin"])/2 + df[,"xmin"]
ycoords <- (df[,"ymax"] - df[,"ymin"])/2 + df[,"ymin"]

#create dataframe from coordinates
points <-data.frame("x"=c(xcoords),
"y"=c(ycoords))
#create raster
ras <- raster(SpatialPoints(points))

Is it possible to write a single function to create raster files from a data.frame object?

It’s always much easier to help when we have sample data we can use. In the future you can use dput(prec) and copy and paste that output for people to use. At the very least some sample data is useful, particularly when you’re using functions that have certain specifications for what the data should look like. Here we generate some data to work with.

library(raster)
#> Loading required package: sp
library(data.table)
#>
#> Attaching package: 'data.table'
#> The following object is masked from 'package:raster':
#>
#> shift

set.seed(1)
dat <-
data.frame(
x = rep(seq(-47.8, -47.2, by = 0.2), 241),
y = -21.2,
prec = runif(964),
tstep = rep(1:241, each = 4),
date = c(rep(as.Date("2015-01-01"), 4), rep(seq(as.Date("2015-01-01"), by = "day", length.out = 60), each = 16))
)

For your process, it seems a bit more straightforward to group the data rather than break it up. That way you only have to perform the operations on one data set rather than do it many times over. Steps 1 and 2 can be reduced to only a few lines that way. Without thinking too much about optimizing this, I’ve looped over the groups created in the first step to create the raster layers.

raster_layers <- function(dat){

## some flexibility if there is a differing number of tsteps
## it will by default exclude the first tstep as in your example
min_tstep <- min(dat$tstep)
max_tstep <- max(dat$tstep)
breaks <- seq(min_tstep, max_tstep, by = 4)

## Step 1
dat$group <- cut(dat$tstep, breaks)
dat <- dat[!is.na(dat$group), ]
## Step 2
prec <- setDT(dat)[ , list(prec_sum = sum(prec * 1000)), by = list(group, x, y)]
## Step 3
layer <- list()
group <- unique(prec$group)
j <- 1
for (i in group){

raster_dat <- prec[prec$group %in% i , c("x", "y", "prec_sum")]
## looks like your plot uses the names for changing labels??
colnames(raster_dat)[colnames(raster_dat) == "prec_sum"] <- paste0("prec_sum_", j)
layer[[j]] <-
rasterFromXYZ(raster_dat,
res = c(0.20, 0.20),
crs = sp::CRS("+init=epsg:4326"))
j <- j + 1
}
## Step 4
stack_prec <- stack(unlist(layer))

return(stack_prec)
}

Example

stack_prec <- raster_layers(dat = dat)

stack_prec
#> class : RasterStack
#> dimensions : 1, 4, 4, 60 (nrow, ncol, ncell, nlayers)
#> resolution : 0.2, 0.2 (x, y)
#> extent : -47.9, -47.1, -21.3, -21.1 (xmin, xmax, ymin, ymax)
#> crs : +init=epsg:4326
#> names : prec_sum_1, prec_sum_2, prec_sum_3, prec_sum_4, prec_sum_5, prec_sum_6, prec_sum_7, prec_sum_8, prec_sum_9, prec_sum_10, prec_sum_11, prec_sum_12, prec_sum_13, prec_sum_14, prec_sum_15, ...
#> min values : 2112.4990, 1124.8232, 2007.5945, 1315.0517, 1729.9294, 1582.8684, 1524.0147, 1098.1529, 2008.5390, 1248.1860, 1680.0199, 1855.4024, 815.4047, 1204.8576, 1416.3943, ...
#> max values : 2336.186, 2565.158, 2877.219, 2318.115, 3017.609, 2540.536, 2569.019, 2690.884, 2327.706, 2288.046, 3104.792, 2639.530, 2358.953, 2599.245, 2618.676, ...


Related Topics



Leave a reply



Submit