View or edit on GitHub
This page is synchronized from trase/data/indonesia/palm_oil/logistics/plantations/Q1_2026/id_palm_ffb_prod_unit.md. Last modified on 2026-05-06 16:54 CEST by Trase Admin.
Please view or edit the original file there; changes should be reflected here after a midnight build (CET time),
or manually triggering it with a GitHub action (link).
FFB production unit
Adelina Chandra 2026-03-06
Notes
Preparation
library(dplyr)
library(ggplot2)
library(tidyverse)
library(sf)
library(fs)
library(aws.signature)
library(aws.s3)
library(arrow)
library(tidylog)
library(lwgeom)
aws.signature::use_credentials()
Sys.setenv("AWS_DEFAULT_REGION" = "eu-west-1")
bucket <- "trase-storage"
Read data
# palm oil concessions
op_conc <- st_read("/vsis3/trase-storage/indonesia/logistics/out/plantations/q1_2026/id_op2025_noOverlaps_v2026.geojson")
Reading layer `id_op2025_noOverlaps_v2026' from data source
`/vsis3/trase-storage/indonesia/logistics/out/plantations/q1_2026/id_op2025_noOverlaps_v2026.geojson'
using driver `GeoJSON'
Simple feature collection with 6663 features and 22 fields
Geometry type: MULTIPOLYGON
Dimension: XY
Bounding box: xmin: 95.2443 ymin: -8.49672 xmax: 140.9885 ymax: 5.809408
Geodetic CRS: WGS 84
# concession links
conc_mill <- st_read("/vsis3/trase-storage/indonesia/logistics/out/plantations/q1_2026/Matching/idn_op2025_conc_matched_2026.geojson")
Reading layer `idn_op2025_conc_matched_2026' from data source
`/vsis3/trase-storage/indonesia/logistics/out/plantations/q1_2026/Matching/idn_op2025_conc_matched_2026.geojson'
using driver `GeoJSON'
Simple feature collection with 10192 features and 33 fields (with 4 geometries empty)
Geometry type: GEOMETRY
Dimension: XY
Bounding box: xmin: 95.2443 ymin: -8.49672 xmax: 140.9885 ymax: 5.809408
Geodetic CRS: WGS 84
conc_mill <- conc_mill %>% dplyr::filter(!st_is_empty(geometry))
# old ffb production unit
ffb_o <- st_read("/vsis3/trase-storage/indonesia/production/out/CONC_KAB_SPLIT_BY_KEC.geojson")
Reading layer `file6b202d963237' from data source
`/vsis3/trase-storage/indonesia/production/out/CONC_KAB_SPLIT_BY_KEC.geojson'
using driver `GeoJSON'
Simple feature collection with 11891 features and 4 fields
Geometry type: MULTIPOLYGON
Dimension: XY
Bounding box: xmin: 94.97195 ymin: -11.00762 xmax: 141.02 ymax: 6.076768
Geodetic CRS: WGS 84
# took too long to process in R, did union in QGIS
ffb_n <- st_read("/vsis3/trase-storage/indonesia/production/out/q1_2026/idn_conc_kec_v2026.geojson")
Reading layer `idn_conc_kec_v2026' from data source
`/vsis3/trase-storage/indonesia/production/out/q1_2026/idn_conc_kec_v2026.geojson'
using driver `GeoJSON'
Simple feature collection with 18510 features and 32 fields
Geometry type: MULTIPOLYGON
Dimension: XY
Bounding box: xmin: 94.97191 ymin: -11.00762 xmax: 141.02 ymax: 6.076832
Geodetic CRS: WGS 84
We decided to keep retain old concession codes but have new FFB production unit.
Admin read and preparation
# kab boundaries
# kab <- st_read("/vsis3/trase-storage/indonesia/spatial/BOUNDARIES/big/out/q1_2026/kabupaten_boundaries_2023_v2026.geojson")
#kec boundaries
kec <- st_read("/vsis3/trase-storage/indonesia/spatial/BOUNDARIES/big/out/q1_2026/kecamatan_boundaries_2023_v2026.geojson")
Reading layer `kecamatan_boundaries_2023_v2026' from data source
`/vsis3/trase-storage/indonesia/spatial/BOUNDARIES/big/out/q1_2026/kecamatan_boundaries_2023_v2026.geojson'
using driver `GeoJSON'
Simple feature collection with 7325 features and 10 fields
Geometry type: MULTIPOLYGON
Dimension: XY
Bounding box: xmin: 94.97191 ymin: -11.00762 xmax: 141.02 ymax: 6.076832
Geodetic CRS: WGS 84
# proj: Cylindrical Equal Area
indonesian_crs <- "+proj=cea +lon_0=115.0 +lat_ts=0 +x_0=0 +y_0=0 +ellps=WGS84 +units=m +no_defs"
Took too long than expected to merge - skipped and did this in QGIS to speed up
# kec_prep <- kec %>%
# mutate(kec_id = paste0("KEC", gsub("\\.", "", as.character(kec_code))))
# kec_in_op <- st_intersection(kec_prep %>% select(kec_id), op_conc %>% select(code))
# op_union <- st_union(op_conc)
# kec_out_op <- st_difference(kec_prep, op_union)
# kec_partitioned <- bind_rows(
# kec_in_op %>% mutate(part = "intersect"),
# kec_out_op %>% mutate(part = "outside"))
Clean up merged data
glimpse(ffb_o)
Rows: 11,891
Columns: 5
$ kab_code <dbl> 3208, 3208, 3208, 3208, 3208, 3304, 3304, 3304, 3304, 3304, …
$ prov_code <dbl> 32, 32, 32, 32, 32, 33, 33, 33, 33, 33, 33, 33, 35, 35, 35, …
$ ffb_code <chr> "FFB-00001", "FFB-00002", "FFB-00003", "FFB-00004", "FFB-000…
$ conc_code <chr> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, …
$ geometry <MULTIPOLYGON [°]> MULTIPOLYGON (((108.4436 -6..., MULTIPOLYGON ((…
glimpse(ffb_n)
Rows: 18,510
Columns: 33
$ code <chr> "BPN0823", "BPN0823", "BPN0823", "GPC1079", "BPN0228", "BPN…
$ dataSource <chr> "BPN", "BPN", "BPN", "Greenpeace", "BPN", "BPN", "BPN", "BP…
$ company <chr> "PT Sinar Gunung Sawit Raya", "PT Sinar Gunung Sawit Raya",…
$ group_ <chr> "Andalas Lestari International / Mujur Timber", "Andalas Le…
$ rspoCert_c <chr> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA,…
$ extra_data <chr> "company name from GC", "company name from GC", "company na…
$ geoPresenc <chr> "no", "no", "no", "no", "no", "no", "no", "no", "no", "no",…
$ geoOwner <chr> "NA", "NA", "NA", "NA", "NA", "NA", "NA", "NA", "NA", "NA",…
$ aerialPres <chr> "yes", "yes", "yes", "unclear", "yes", "yes", "yes", "yes",…
$ notes <chr> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, "gc cal…
$ NIB <chr> "02.14.00.00.00016", "02.14.00.00.00016", "02.14.00.00.0001…
$ NO_HAK <chr> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA,…
$ legalStatu <chr> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA,…
$ admin0 <chr> "Indonesia", "Indonesia", "Indonesia", "Indonesia", "Indone…
$ joinDate <chr> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA,…
$ status <chr> "NA", "NA", "NA", "NA", "NA", "NA", "NA", "NA", "NA", "NA",…
$ memberNumb <chr> "NA", "NA", "NA", "NA", "NA", "NA", "NA", "NA", "NA", "NA",…
$ rspoMember <chr> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA,…
$ georspoCer <chr> "NA", "NA", "NA", "NA", "NA", "NA", "NA", "NA", "NA", "NA",…
$ memberYear <chr> "NA", "NA", "NA", "NA", "NA", "NA", "NA", "NA", "NA", "NA",…
$ newedit <chr> "old", "old", "old", "old", "old", "old", "old", "old", "ol…
$ area_ha <dbl> 7157.739, 7157.739, 7157.739, 1465.951, 27.601, 27.601, 30.…
$ fid <int> 196, 318, 324, 6423, 6186, 6198, 6186, 6198, 6186, 6198, 61…
$ metadata <chr> "TASWIL1000020230928_DATA_BATAS_KECAMATAN", "TASWIL10000202…
$ prov_name <chr> "Aceh", "Sumatera Utara", "Sumatera Utara", "Maluku Utara",…
$ kab_name <chr> "Aceh Singkil", "Tapanuli Tengah", "Tapanuli Tengah", "Halm…
$ kec_code <chr> "11.10.11", "12.01.05", "12.01.11", "82.02.07", "75.04.01",…
$ kab_code <chr> "11.10", "12.01", "12.01", "82.02", "75.04", "75.04", "75.0…
$ prov_code <chr> "11", "12", "12", "82", "75", "75", "75", "75", "75", "75",…
$ kec_name <chr> "Danau Paris", "Manduamas", "Sirandorung", "Weda Tengah", "…
$ shape_area <dbl> 336483685, 305702048, 107826715, 541315295, 61508005, 40580…
$ trase_id <chr> "ID-111011", "ID-120105", "ID-120111", "ID-820207", "ID-750…
$ geometry <MULTIPOLYGON [°]> MULTIPOLYGON (((98.12695 2...., MULTIPOLYGON (…
#check area
kec_proj <- st_transform(kec, indonesian_crs)
ffb_proj <- st_transform(ffb_n, indonesian_crs)
sum(as.numeric(st_area(ffb_proj)))
[1] 1.89108e+12
sum(as.numeric(st_area(kec_proj))) #great!
[1] 1.890904e+12
#prepare details
ffb_prep <- ffb_n %>%
mutate(kec_code = gsub("\\.", "", as.character(kec_code)),
kab_code = gsub("\\.", "", as.character(kab_code)),
ffb_code = paste0("FFB", sprintf("%06d", row_number())),,
conc_code = code) %>%
select(kec_code, kab_code, prov_code, conc_code, ffb_code, kec_code, geometry)
print(glimpse(ffb_prep))
Rows: 18,510
Columns: 6
$ kec_code <chr> "111011", "120105", "120111", "820207", "750401", "750412", …
$ kab_code <chr> "1110", "1201", "1201", "8202", "7504", "7504", "7504", "750…
$ prov_code <chr> "11", "12", "12", "82", "75", "75", "75", "75", "75", "75", …
$ conc_code <chr> "BPN0823", "BPN0823", "BPN0823", "GPC1079", "BPN0228", "BPN0…
$ ffb_code <chr> "FFB000001", "FFB000002", "FFB000003", "FFB000004", "FFB0000…
$ geometry <MULTIPOLYGON [°]> MULTIPOLYGON (((98.12695 2...., MULTIPOLYGON ((…
Simple feature collection with 18510 features and 5 fields
Geometry type: MULTIPOLYGON
Dimension: XY
Bounding box: xmin: 94.97191 ymin: -11.00762 xmax: 141.02 ymax: 6.076832
Geodetic CRS: WGS 84
First 10 features:
kec_code kab_code prov_code conc_code ffb_code
1 111011 1110 11 BPN0823 FFB000001
2 120105 1201 12 BPN0823 FFB000002
3 120111 1201 12 BPN0823 FFB000003
4 820207 8202 82 GPC1079 FFB000004
5 750401 7504 75 BPN0228 FFB000005
6 750412 7504 75 BPN0228 FFB000006
7 750401 7504 75 BPN0472 FFB000007
8 750412 7504 75 BPN0472 FFB000008
9 750401 7504 75 BPN0497 FFB000009
10 750412 7504 75 BPN0497 FFB000010
geometry
1 MULTIPOLYGON (((98.12695 2....
2 MULTIPOLYGON (((98.24567 2....
3 MULTIPOLYGON (((98.28083 2....
4 MULTIPOLYGON (((128.0005 0....
5 MULTIPOLYGON (((121.4944 0....
6 MULTIPOLYGON (((121.4964 0....
7 MULTIPOLYGON (((121.4859 0....
8 MULTIPOLYGON (((121.4846 0....
9 MULTIPOLYGON (((121.4758 0....
10 MULTIPOLYGON (((121.471 0.5...
ffb_prep <- ffb_prep %>%
st_make_valid() %>%
filter(!st_is_empty(geometry))
Save data
st_write(
ffb_prep,
"/vsis3/trase-storage/indonesia/production/out/q1_2026/idn_ffb_unit_v2026.geojson",
delete_dsn = TRUE
)
Deleting source `/vsis3/trase-storage/indonesia/production/out/q1_2026/idn_ffb_unit_v2026.geojson' using driver `GeoJSON'
Writing layer `idn_ffb_unit_v2026' to data source
`/vsis3/trase-storage/indonesia/production/out/q1_2026/idn_ffb_unit_v2026.geojson' using driver `GeoJSON'
Writing 18417 features with 5 fields and geometry type Unknown (any).