1

I have an integer raster of a classification result. Now I want to replace the classes by float values from a dataframe, i.e. raster class 1 = 0.321; Class 2 = 0.232; Class 3 = 3.211. The dataframe has many columns and I want to replace the classes for several different cases:

Class C      N      ....
1    0.321   0.001 
2    0.232   0.012 
3    3.211   0.021 

Is there a way to do this conveniently, like merging the data.frame into the raster? I need to multiply the resulting raster with another raster to generate my outputs.

This is the metadata of the raster file:

 > LCC
 class       : RasterLayer 
 dimensions  : 3296, 3711, 12231456  (nrow, ncol, ncell)
 resolution  : 2, 2  (x, y)
 extent      : 514151.8, 521573.8, 7856419, 7863011  (xmin, xmax, ymin, ymax)
 coord. ref. : +proj=utm +zone=55 +datum=WGS84 +units=m +no_defs +ellps=WGS84 +towgs84=0,0,0 
 data source : /home/..../Raster.tif 
 names       : Raster 
 values      : 0, 255  (min, max)

`

and this the metadata of the dataframe:

 >str(SOC)
 data.frame':   11 obs. of  57 variables:
  $ class             : int  8 9 5 6 7 4 1 2 3 0 ...
  $ area              : int  3135964 3941744 9048672 8564312 11568512     
  $ pixel_count       : int  783991 985436 2262168 2141078 2892128 ...
  $ percent_area      : Factor w/ 11 levels "0.17%","17.50%",..: 9 11 3 2 
  $ label.x           : Factor w/ 11 levels "Barren",..: 5 8 2 
  $ label.y           : Factor w/ 8 levels "Barren",..: 4 7 2 
  $ n                 : int  7 4 4 3 4 1 1 NA NA NA ...
  $ mean_C_100cm      : num  25.8 29 21.3 34.8 31.9 ...
  $ mean_N_100cm      : num  0.469 0.514 0.503 0.621 0.34 ...
 ....

`

mace
  • 490
  • 1
  • 7
  • 24

3 Answers3

5

There is a function (subs) for that.

Example data (following achaio)

library(raster)
inp <- raster(ncol=10, nrow=10) 
set.seed(42)
inp[] <- sample(3, ncell(inp), replace=TRUE)
df <- data.frame(Class=c(1,2,3), C=c(0.321,0.232,3.211), N=c(0.001,0.012,0.021))

To replace the identifier with "C" you can do

x <- subs(inp, df, by=1, which=2)

Or, to get both "C" and "N", do

y <- subs(inp, df, by=1, which=2:3)

Indeed, as mace points out, you can also use reclassify (but only for a single variable at at time)

z <- reclassify(inp, as.matrix(df)[, 1:2])
Robert Hijmans
  • 40,301
  • 4
  • 55
  • 63
1

If I understand what you want correctly, then you can assign the values of a raster using the values in a column in df by:

inp[] <- df[inp[],"C"]

where df is as you defined and inp is the integer raster with values from 1 to 3.

For example:

library(raster)
set.seed(42)  ## for reproducibility

inp <- raster(ncol=10, nrow=10) ## example is small, yours will be large
inp[] <- floor(runif(ncell(inp), min=1, max=4))  ## generate integers from 1 to 3
inp[]
##  [1] 3 3 1 3 2 2 3 1 2 3 2 3 3 1 2 3 3 1 2 2 3 1 3 3 1 2 2 3 2 3 3 3 2 3 1 3 1 1 3 2 2 2 1 3 2 3 3 2
## [49] 3 2 2 2 2 3 1 3 3 1 1 2 3 3 3 2 3 1 1 3 3 1 1 1 1 2 1 3 1 2 2 1 2 1 2 2 3 2 1 1 1 1 3 1 1 3 3 3
## [97] 1 2 3 2

df <- data.frame(Class=c(1,2,3), C=c(0.321,0.232,3.211), N=c(0.001,0.012,0.021))  ## your df

## generate output raster the same size as inp
out <- raster(ncol=10,nrow=10)
## map values of out to values in column C of df
## can overwrite inp here if desired, but for example we want to keep inp
## for following steps
out[] <- df[inp[],"C"]
out[]
##  [1] 3.211 3.211 0.321 3.211 0.232 0.232 3.211 0.321 0.232 3.211 0.232 3.211 3.211 0.321 0.232 3.211
## [17] 3.211 0.321 0.232 0.232 3.211 0.321 3.211 3.211 0.321 0.232 0.232 3.211 0.232 3.211 3.211 3.211
## [33] 0.232 3.211 0.321 3.211 0.321 0.321 3.211 0.232 0.232 0.232 0.321 3.211 0.232 3.211 3.211 0.232
## [49] 3.211 0.232 0.232 0.232 0.232 3.211 0.321 3.211 3.211 0.321 0.321 0.232 3.211 3.211 3.211 0.232
## [65] 3.211 0.321 0.321 3.211 3.211 0.321 0.321 0.321 0.321 0.232 0.321 3.211 0.321 0.232 0.232 0.321
## [81] 0.232 0.321 0.232 0.232 3.211 0.232 0.321 0.321 0.321 0.321 3.211 0.321 0.321 3.211 3.211 3.211
## [97] 0.321 0.232 3.211 0.232

## can create a brick and add layers that map values from N column of df
out.brick <- brick(x=out)
out[] <- df[inp[],"N"]
out.brick <- addLayer(out.brick, out)
out.brick[[2]][]
##  [1] 0.021 0.021 0.001 0.021 0.012 0.012 0.021 0.001 0.012 0.021 0.012 0.021 0.021 0.001 0.012 0.021
## [17] 0.021 0.001 0.012 0.012 0.021 0.001 0.021 0.021 0.001 0.012 0.012 0.021 0.012 0.021 0.021 0.021
## [33] 0.012 0.021 0.001 0.021 0.001 0.001 0.021 0.012 0.012 0.012 0.001 0.021 0.012 0.021 0.021 0.012
## [49] 0.021 0.012 0.012 0.012 0.012 0.021 0.001 0.021 0.021 0.001 0.001 0.012 0.021 0.021 0.021 0.012
## [65] 0.021 0.001 0.001 0.021 0.021 0.001 0.001 0.001 0.001 0.012 0.001 0.021 0.001 0.012 0.012 0.001
## [81] 0.012 0.001 0.012 0.012 0.021 0.012 0.001 0.001 0.001 0.001 0.021 0.001 0.001 0.021 0.021 0.021
## [97] 0.001 0.012 0.021 0.012

Hope this helps.

aichao
  • 7,375
  • 3
  • 16
  • 18
  • Thanks, it seems to work in the example, but not with my original data that gets heavily distorted. Could it be because the values in the dataframe are stored as numeric? – mace Aug 29 '16 at 13:23
  • @mace can you provide a reasonable size example as to why your data is heavily distorted? It may be that your data has factors instead of just numeric integers. Can you provide the output from the raster (i.e., just print the raster variable to output its metadata) and provide the output from `str(df)` in your post (i.e., edit the post instead of replying to this comment)? – aichao Aug 29 '16 at 13:30
  • Ok, thanks for you help. I figured out a working solution that I will post later on. – mace Aug 29 '16 at 15:51
0

I reworked aichio's example using instead the reclassify function. Here is an approach that worked for me:

library(raster)
set.seed(42)  ## for reproducibility

inp <- raster(ncol=10, nrow=10) ## example is small, yours will be large
inp[] <- floor(runif(ncell(inp), min=1, max=4))  ## generate integers from 1 to 3

df <- data.frame(Class=c(1,2,3), C=c(10.321,1.232,0.211), N=c(0.001,0.012,0.021))  ## your df

## generate output raster the same size as inp
out <- raster(ncol=10,nrow=10)


#### here I generate a matrix that defines the
#### reclassification with an upper and lower limit

mtr <- data.frame(cl_low =df$Class -1, cl_high = df$Class, C =df$C)
data.matrix(mtr)  ### use as matrix

# now reclassify using the matrix and transfer the result in a raster brick

out <- reclassify(inp, rcl=mtr)
out.brick <- brick(x=out)

# now the same can be done for next variable
mtr <- data.frame(cl_low =df$Class -1, cl_high = df$Class, N =df$N)
data.matrix(mtr)
out <- reclassify(inp, rcl=mtr)
out.brick <- addLayer(out.brick, out)
out.brick@layers
Community
  • 1
  • 1
mace
  • 490
  • 1
  • 7
  • 24