rsumr-sfspatial-data-frame

aggregate sf spatial dataframe values


I want to sum the values ​​of each polygon, indicated as cod_area.

library(sf)

sf.data <- structure(list(cod_area = c(34275L, 34275L, 34347L, 34347L), 
    cod_reg = c(1664464L, 1664467L, 1665398L, 1665400L), val = c(2562.5, 
    2166.66666666667, 10288.75, 3613), geometry = structure(list(
        structure(list(structure(c(-46.5, -46.3333333, -46.3333333, 
        -46.5, -46.5, -24.3333333, -24.3333333, -24.5, -24.5, 
        -24.3333333), dim = c(5L, 2L))), class = c("XY", "POLYGON", 
        "sfg")), structure(list(structure(c(-46.5, -46.3333333, 
        -46.3333333, -46.5, -46.5, -24.3333333, -24.3333333, 
        -24.5, -24.5, -24.3333333), dim = c(5L, 2L))), class = c("XY", 
        "POLYGON", "sfg")), structure(list(structure(c(-46.6666667, 
        -46.5, -46.5, -46.6666667, -46.6666667, -24.3333333, 
        -24.3333333, -24.5, -24.5, -24.3333333), dim = c(5L, 
        2L))), class = c("XY", "POLYGON", "sfg")), structure(list(
            structure(c(-46.6666667, -46.5, -46.5, -46.6666667, 
            -46.6666667, -24.3333333, -24.3333333, -24.5, -24.5, 
            -24.3333333), dim = c(5L, 2L))), class = c("XY", 
        "POLYGON", "sfg"))), n_empty = 0L, class = c("sfc_POLYGON", 
    "sfc"), precision = 0, bbox = structure(c(xmin = -46.6666667, 
    ymin = -24.5, xmax = -46.3333333, ymax = -24.3333333), class = "bbox"), crs = structure(list(
        input = "EPSG:4674", wkt = "GEOGCRS[\"SIRGAS 2000\",\n    DATUM[\"Sistema de Referencia Geocentrico para las AmericaS 2000\",\n        ELLIPSOID[\"GRS 1980\",6378137,298.257222101,\n            LENGTHUNIT[\"metre\",1]]],\n    PRIMEM[\"Greenwich\",0,\n        ANGLEUNIT[\"degree\",0.0174532925199433]],\n    CS[ellipsoidal,2],\n        AXIS[\"geodetic latitude (Lat)\",north,\n            ORDER[1],\n            ANGLEUNIT[\"degree\",0.0174532925199433]],\n        AXIS[\"geodetic longitude (Lon)\",east,\n            ORDER[2],\n            ANGLEUNIT[\"degree\",0.0174532925199433]],\n    USAGE[\n        SCOPE[\"Horizontal component of 3D system.\"],\n        AREA[\"Latin America - Central America and South America - onshore and offshore. Brazil - onshore and offshore.\"],\n        BBOX[-59.87,-122.19,32.72,-25.28]],\n    ID[\"EPSG\",4674]]"), class = "crs"))), row.names = c(NA, 
4L), class = c("sf", "data.frame"), sf_column = "geometry", agr = structure(c(cod_area = NA_integer_, 
cod_reg = NA_integer_, val = NA_integer_), class = "factor", levels = c("constant", 
"aggregate", "identity")))

class(sf.data)
[1] "sf"         "data.frame"

I expected to have two values, 4729.167 for cod_area 34275 and 13901.75 for cod_area 34347. But ...

aggregate(val~geometry,data=sf.data,FUN=sum)
Error in model.frame.default(formula = val ~ geometry, data = sf.data) : 
  invalid type (list) for variable 'geometry'


aggregate(sf.data["val"],by=list(sf.data$geometry),FUN=sum)
Error in order(y) : unimplemented type 'list' in 'orderVector1'

among other attempts. I somehow solved the problem with

agg.val <- aggregate(val~cod_area,sf.data,FUN=sum)

merge(agg.val,unique(sf.data[,1]),by="cod_area")

Is there a more direct way to do the calculation (without using dplyr)?


Solution

  • You can set the do_union parameter to TRUE (but it doesn't seem to work with the formula method):

    aggregate(sf.data, list(cod_area = sf.data$cod_area), FUN=sum, do_union = TRUE)
    
    
    
    Simple feature collection with 2 features and 4 fields
    Attribute-geometry relationships: aggregate (3), identity (1)
    Geometry type: POLYGON
    Dimension:     XY
    Bounding box:  xmin: -46.66667 ymin: -24.5 xmax: -46.33333 ymax: -24.33333
    Geodetic CRS:  SIRGAS 2000
      cod_area cod_area.1 cod_reg       val                       geometry
    1    34275      68550 3328931  4729.167 POLYGON ((-46.33333 -24.333...
    2    34347      68694 3330798 13901.750 POLYGON ((-46.5 -24.33333, ...