View or edit on GitHub
This page is synchronized from trase/products/analysis/notebooks/engagement/brazil_beef/MARFRIG/2025_CHECK_FULL_CYCLE_FARMS.md. Last modified on 2026-02-03 10:30 CET by Jason J. Benedict.
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).
Check Marfrig full-cycle ranches
Erasmus 2025-06-03
This script exports a list of the CPFs and GEOCODE of Marfrig’s supplier properties in Mato Grosso (as disclosed for 2023 and 2024).
Specifically, we take the supplier lists for 2023 and 2024 and cross
them with CAR data for Mato Grosso which we have (from circa year 2020).
This allows us to identify their CPFs and municipality. In a later step
(in BigQuery) we will count the number of animals purchases by
properties of different classifications: CRIA;RECRIA;ENGORDA,
ENGORDA, and RECRIA;ENGORDA in order to verify Marfrig’s claim that
CRIA;RECRIA;ENGORDA farms are ‘origin controlled’ (i.e. they don’t buy
any cattle).
# Load CAR in MT
# ... extract the GEOCODE from the COD_IMOVEL
# ... I got an error when loading the CAR data onto S3, therefore work from a local copy instead
car <- read_sf("C:/Users/erasm/Desktop/CAR/car_mt_20170823_v2.shp") %>%
janitor::clean_names("screaming_snake") %>%
mutate(GEOCODE = sub('.*MT-', '', COD_IMOVEL),
GEOCODE = sub('-.*', '', GEOCODE))
## Re-reading with feature count reset from 112463 to 100716
# Load states
path <- "brazil/spatial/boundaries/ibge/old/boundaries states/"
keys <- map_chr(get_bucket(ts, prefix = path), "Key")
walk(keys, ~ save_object(., ts, file = str_c(tempdir(),"/", basename(.))))
objects <- list.files(tempdir(), pattern = "BRUFE250GC_SIR", full.names = TRUE)
objects_main <- objects[grepl("\\.shp", objects)]
states <- read_sf(objects_main)
rm(path, keys, objects, objects_main)
# [A] Direct suppliers in 2024
dir_suppliers <- s3read_using(
object = "brazil/beef/norges_council/input/2024-Relação de Fazendas Diretas e Indiretas - Amz e Cerrado.xlsx",
FUN = read_excel,
bucket = ts,
sheet = "Diretos",
skip = 1) %>%
mutate(POSITION = "DIRECT") %>%
janitor::clean_names("screaming_snake") %>%
mutate(YEAR = 2024)
# [A] Direct suppliers in 2023
dir_suppliers_2023 <- s3read_using(
object = "brazil/beef/norges_council/input/CAR - Fazendas Set 2021 a Ago 2022 (Detalhes volume e risco).xlsx",
FUN = read_excel,
bucket = ts
) %>%
mutate(POSITION = "DIRECT") %>%
janitor::clean_names("screaming_snake") %>%
rename(LEVEL_RISK = RISCO,
PRODUCTION_CYCLE = SISTEMA_DE_PRODUCAO,
CATTLE = NO_DE_ANIMAIS,
WEIGHT_KG = PESO_KG) %>%
mutate(YEAR = 2023)
# Identify supplier matches in CAR
supplier_car <- bind_rows(
"2024 DISCLOSURE" = dir_suppliers,
"2023 DISCLOSURE" = dir_suppliers_2023,
.id = "SOURCE"
) %>%
mutate(STATE = str_sub(CAR, start = 1, end = 2)) %>%
mutate(PRODUCTION_CYCLE = gsub(",", ";", str_to_upper(PRODUCTION_CYCLE))) %>%
right_join(car, ., by = c("COD_IMOVEL" = "CAR")) %>%
select(SOURCE, CAR = COD_IMOVEL, COD_CPF_CN, STATE, GEOCODE, PRODUCTION_CYCLE)
# How many matches?
supplier_car %>%
st_drop_geometry() %>%
mutate(SUPPLIER = ifelse(is.na(COD_CPF_CN), "NOT MATCHED", "MATCHED TO CAR")) %>%
count(SOURCE, STATE, SUPPLIER, PRODUCTION_CYCLE) %>%
ggplot(aes(PRODUCTION_CYCLE, n, fill = SUPPLIER)) +
facet_wrap(~SOURCE) +
geom_bar(stat = "identity", position = "dodge") +
theme_trase() +
theme(axis.text.x = element_text(angle = 45, hjust = 1))

Visualise their locations
ggplot() +
geom_sf(data = states %>% filter(NM_ESTADO == "MATO GROSSO"), fill = trase_country_background, col = trase_map_border) +
geom_sf(data = supplier_car) +
theme_trase() +
theme(axis.text = element_blank()) +
coord_sf(datum = NA) +
labs(title = "Marfrig suppliers in MT matched to CAR (with CPF)",
subtitle = paste0(supplier_car %>% drop_na(COD_CPF_CN) %>% nrow(), " properties across 2023-2024"))

# Export the list of suppliers
# ... Adding column to note if multiple CPFs per CAR
# ... Extract one row per CPF
supplier_car %>%
drop_na(COD_CPF_CN) %>%
mutate(CPF_NUM = str_count(COD_CPF_CN, ";") + 1,
CPF = str_split(string = COD_CPF_CN, pattern = ";")) %>%
unnest(cols = c(CPF)) %>%
select(-CPF_NUM) %>%
s3write_using(
x = .,
object = "brazil/beef/norges_council/results/Report_Jan_2025/FULL_CYCLE_RANCHES.geojson",
FUN = write_sf,
bucket = ts,
opts = c(multipart = TRUE)
)