Search code examples
rrasterr-raster

Transform raster data to data.frame


I have multiple rasters and the idea is to create a column for each layer inside a data frame, but I'd like to use mydf$layername or mydf[[layername]] operations in a loop. In my example:

library(raster)

Create an empty data frame:

mydf<-NULL

3 layers simulation:

## Create a simulated RBG rasters
r <- raster(nc=30, nr=30)
r <- setValues(r, round(runif(ncell(r))* 255))
g <- raster(nc=30, nr=30)
g <- setValues(r, round(runif(ncell(r))* 255))
b <- raster(nc=30, nr=30)
b <- setValues(r, round(runif(ncell(r))* 255))
rgb<-stack(r,g,b)

Population of data frame(mydf) with each layer information and use "names" as a variable name

for (i in 1:length(rgb@layers)){
mydf$assign(paste0(rgb[[i]]@layers)) <- as(as.im(rgb[[i]]), "SpatialGridDataFrame")$v
}
Error in mydf$assign(paste0(rgb[[i]]@data@names)) <- as(as.im(rgb[[i]]),  :

or


for (i in 1:length(rgb@layers)){
     mydf[[assign(paste0(rgb[[i]]@layers))]] <- as(as.im(rgb[[i]]), "SpatialGridDataFrame")$v
}
Error in paste0(rgb[[i]]@layers) : 

There is any solution for this mydf$assign(paste0(rgb[[i]]@layers)) or mydf[[assign(paste0(rgb[[i]]@layers))]] operations?


Solution

  • 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)