Example simple feature to data frame…

library(sf)
## Linking to GEOS 3.10.2, GDAL 3.4.2, PROJ 8.2.1; sf_use_s2() is TRUE
library(ggseg)
library(tidyverse)
## ── Attaching core tidyverse packages ──────────────────────── tidyverse 2.0.0 ──
## ✔ dplyr     1.1.0     ✔ readr     2.1.4
## ✔ forcats   1.0.0     ✔ stringr   1.5.0
## ✔ ggplot2   3.4.1     ✔ tibble    3.1.8
## ✔ lubridate 1.9.2     ✔ tidyr     1.3.0
## ✔ purrr     1.0.1
## ── Conflicts ────────────────────────────────────────── tidyverse_conflicts() ──
## ✖ dplyr::filter() masks stats::filter()
## ✖ dplyr::lag()    masks stats::lag()
## ℹ Use the conflicted package (<http://conflicted.r-lib.org/>) to force all conflicts to become errors
dk_geometries_frame <- ggseg::dk$data
aseg_geometries_frame <- ggseg::aseg$data


aseg_df <- ggseg::aseg$data
aseg_df$geometry <- NULL
aseg_df <- aseg_df %>% data.frame() %>% remove_missing()
## Warning: Removed 3 rows containing missing values.
aseg_df %>% count(label)
##                            label n
## 1                     Brain-Stem 1
## 2                    CC_Anterior 1
## 3                     CC_Central 1
## 4                CC_Mid_Anterior 1
## 5               CC_Mid_Posterior 1
## 6                   CC_Posterior 1
## 7                  Left-Amygdala 1
## 8                   Left-Caudate 1
## 9               Left-Hippocampus 1
## 10        Left-Lateral-Ventricle 1
## 11                 Left-Pallidum 1
## 12                  Left-Putamen 1
## 13          Left-Thalamus-Proper 1
## 14                Left-VentralDC 1
## 15                Right-Amygdala 1
## 16                 Right-Caudate 1
## 17       Right-Cerebellum-Cortex 1
## 18 Right-Cerebellum-White-Matter 1
## 19             Right-Hippocampus 1
## 20       Right-Lateral-Ventricle 1
## 21                Right-Pallidum 1
## 22                 Right-Putamen 1
## 23         Right-Thalamus-Proper 1
## 24               Right-VentralDC 1
## 25                x3rd-ventricle 1
## 26                x4th-ventricle 1
# aseg_df %>% #count(region)
  # mutate(label = label %>% as.factor()) %>% 
ggplot() + 
  aes(seg_label = label) +  # name indicates position instead of x and y 
  geom_sf(data = ggseg::aseg$data)

last_plot() %>% layer_data() %>% select(seg_label, geometry, xmin, xmax, ymin, ymax) %>% filter(!is.na(seg_label)) ->
  reference
compute_brain_segs <- function(data, scales){
 
  data %>% 
    inner_join(reference)
  
}

Step 2: pass to ggproto

StatBseg <- ggplot2::ggproto(`_class` = "StatBseg",
                                  `_inherit` = ggplot2::Stat,
                                  compute_panel = compute_brain_segs,
                                  default_aes = aes(geometry = after_stat(geometry))
                                  )

Step 3: write geom_* function

geom_sf_brainsegs <- function(
  mapping = NULL,
  data = NULL,
  position = "identity",
  na.rm = FALSE,
  show.legend = NA,
  inherit.aes = TRUE, ...) {
  ggplot2::layer(
    stat = StatBseg,  # proto object from step 2
    geom = ggplot2::GeomSf,  # inherit other behavior
    data = data,
    mapping = mapping,
    position = position,
    show.legend = show.legend,
    inherit.aes = inherit.aes,
    params = list(na.rm = na.rm, ...)
  )
}

step 4: test geom_* function, celebrate!

c("Left-Thalamus-Proper",
"Right-Thalamus-Proper" ,
"Right-Lateral-Ventricle",
"Left-Hippocampus"  ,
"Left-Lateral-Ventricle",
"Right-Putamen" ,
"Right-Amygdala") %>% tibble(my_segs = .) %>% 
  ggplot() + 
  aes(seg_label = my_segs) +
  coord_sf() +
  geom_sf(data = aseg$data, 
          aes(seg_label = NULL) # huh?  required?
          ) +
  geom_sf_brainsegs(fill = "darkred", alpha = .5) + 
  geom_sf_text(aes(label = label, seg_label = NULL), 
               data = aseg$data, size = 2, color = "blue", angle = 20)
## Coordinate system already present. Adding new coordinate system, which will
## replace the existing one.
## Joining with `by = join_by(seg_label)`
## Warning: Removed 3 rows containing missing values (`geom_text()`).