5

I have a raster (seg) whose values I want to substitute, and am getting an error from function subs from the raster package that I don't understand at all.

I get the following error

Error in .local(x, y, ...) : duplicate "by" values not allowed

Even though I have no duplicates in my data frame.

The error show up with both of the following commands, which makes no sense to me.

seg <- subs(seg, tabulated, by="seg", which="class")
seg <- subs(seg, tabulated[which(!duplicated(tabulated$seg)),], by="seg", which="class")

From what i could find out from subs, it checks duplicates through the following commands

tt <- table(tabulated$seg)
tt <- tt[ which(tt > 1) ]
if (length(tt) > 0) {
  stop('duplicate "by" values not allowed')
}

When I run those commands myself I find that tt has a length of 0...

I am not sure how to share the specifics, so I copied the structure of the two objects. The dataframe has 5784018 rows, which corresponds to the number of unique values of the raster seg.

I am not sure what I am missing.

The structure of my raster is the following

Formal class 'RasterLayer' [package "raster"] with 12 slots
  ..@ file    :Formal class '.RasterFile' [package "raster"] with 13 slots
  .. .. ..@ name        : chr "/media/olivier/olivier_ext/gedata_current/jde_coffee/data/ES/Classifs/test/es3_seg2.tif"
  .. .. ..@ datanotation: chr "INT4S"
  .. .. ..@ byteorder   : chr "little"
  .. .. ..@ nodatavalue : num -Inf
  .. .. ..@ NAchanged   : logi FALSE
  .. .. ..@ nbands      : int 1
  .. .. ..@ bandorder   : chr "BIL"
  .. .. ..@ offset      : int 0
  .. .. ..@ toptobottom : logi TRUE
  .. .. ..@ blockrows   : int 1
  .. .. ..@ blockcols   : int 11497
  .. .. ..@ driver      : chr "gdal"
  .. .. ..@ open        : logi FALSE
  ..@ data    :Formal class '.SingleLayerData' [package "raster"] with 13 slots
  .. .. ..@ values    : logi(0) 
  .. .. ..@ offset    : num 0
  .. .. ..@ gain      : num 1
  .. .. ..@ inmemory  : logi FALSE
  .. .. ..@ fromdisk  : logi TRUE
  .. .. ..@ isfactor  : logi FALSE
  .. .. ..@ attributes: list()
  .. .. ..@ haveminmax: logi TRUE
  .. .. ..@ min       : num -2.15e+09
  .. .. ..@ max       : num 2.15e+09
  .. .. ..@ band      : int 1
  .. .. ..@ unit      : chr ""
  .. .. ..@ names     : chr "es3_seg2"
  ..@ legend  :Formal class '.RasterLegend' [package "raster"] with 5 slots
  .. .. ..@ type      : chr(0) 
  .. .. ..@ values    : logi(0) 
  .. .. ..@ color     : logi(0) 
  .. .. ..@ names     : logi(0) 
  .. .. ..@ colortable: logi(0) 
  ..@ title   : chr(0) 
  ..@ extent  :Formal class 'Extent' [package "raster"] with 4 slots
  .. .. ..@ xmin: num 268734
  .. .. ..@ xmax: num 337716
  .. .. ..@ ymin: num 7714422
  .. .. ..@ ymax: num 7828590
  ..@ rotated : logi FALSE
  ..@ rotation:Formal class '.Rotation' [package "raster"] with 2 slots
  .. .. ..@ geotrans: num(0) 
  .. .. ..@ transfun:function ()  
  ..@ ncols   : int 11497
  ..@ nrows   : int 19028
  ..@ crs     :Formal class 'CRS' [package "sp"] with 1 slot
  .. .. ..@ projargs: chr "+proj=utm +zone=24 +south +datum=WGS84 +units=m +no_defs +ellps=WGS84 +towgs84=0,0,0"
  ..@ history : list()
  ..@ z       : list()

And the structure of the data frame is

'data.frame':   5784018 obs. of  3 variables:
 $ class: int  2 6 6 2 2 6 11 7 7 7 ...
 $ seg  : int  1 3 6 8 10 15 18 21 22 24 ...
 $ freq : int  2504 375 31 4 102 109 3 6 7 7 ...
  • What does length(unique(tabulated$seg)) return? It should be 5784018. Do you really have that many unique values in the data.frame that match your raster? I think that the error is likely valid. – Jeffrey Evans Sep 3 '16 at 1:32
  • Yes, this is the number of unique values. The raster is a raster of spatial segments computed from a satellite image at 6m resolution, so there are indeed many of them. But the number of unique values to replace in the raster shouldn't be an issue? – Olivier Sep 3 '16 at 7:45
2

Update: The bug that causes this problem was fixed in version 2.8-2 of the raster package.

In version 2.8-1 of the raster package (and earlier ones also) raster::subs has a bug that causes it to fail when the by argument is not the first column.

As a workaround, you could probably get it to work by putting the seg column first:

seg = seg[, c("seg", "class", "freq")]

2

I found a solution, which doesn't make much sense, except if there is some metadata in the dataframe information?

Anyway, the solution is to transform the dataframe into a matrix and back into a dataframe, as follows.

seg <- subs(seg, as.data.frame(as.matrix(tabulated[,c("seg","class")])), by="seg", which="class")
  • You must of had unintentional formatting of a column in your data.frame object. For example, if you run tapply and join to a data.frame without coercing to a vector you end up with an array column. Take a look at what "str" returns on your raw data.frame. Coercing to a matrix and back to a data.frame just removes this formatting and could probably be avoided earlier in your workflow. This is why it is important to include ALL of your code and not just where you are getting an error. – Jeffrey Evans Sep 6 '16 at 17:20

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.