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
Override Column Types When Importing Data Using Readr::Read_Csv() When There Are Many Columns
Deleting Rows That Are Duplicated in One Column Based on the Conditions of Another Column
Apply Grouped Model Back Onto Data
How to Get Parameters from Config File in R Script
Replace Na with Zero in Dplyr Without Using List()
How to Create Datatable with Complex Header in R Shiny
R - Run Source() in Background
Cast Function Argument as a Character String
Multiple Graphs Over Multiple Pages Using Ggplot
Change the Color and Font of Text in Shiny App
R Shiny: Download Existing File
How to Check the Existence of a Downloaded File
Ggplot2:Adding Two Errorbars to Each Point in Scatterplot
R: Text Progress Bar in for Loop
R: Determine If a Script Is Running in Windows or Linux