depth_map_app / helpers.R
edgarodriguez's picture
Upload 5 files
707b5cb verified
Raw
History Blame Contribute Delete
2.92 kB
# ── Shared helpers ─────────────────────────────────────────────────────────────
library(sf)
library(dplyr)
library(stringr)
# Hierarchy codes from nivel8 via str_sub truncation (one char per level up)
add_nivel_codes <- function(sf_obj) {
st_join(sf_obj, nivel8_all |> select(codigo_n4:codigo_n8), join = st_within)
}
# Safe column name from category string
safe_cat <- function(x) {
x |>
tolower() |>
str_replace_all("[^a-z0-9]+", "_") |>
str_replace_all("^_|_$", "")
}
# Formatted number for UI display
fmt_n <- function(x, digits = 0) {
if (all(is.na(x))) return("β€”")
format(round(sum(x, na.rm = TRUE), digits), big.mark = ",", scientific = FALSE)
}
fmt_avg <- function(x, digits = 1) {
if (all(is.na(x))) return("β€”")
format(round(mean(x, na.rm = TRUE), digits), big.mark = ",", scientific = FALSE)
}
# DuckDB connection helper with spatial + httpfs extensions loaded.
# Uses duckdb(dbdir = path) so the driver object is created with the correct path
# upfront (avoids a class of GC-related "Invalid connection" errors).
# Tries LOAD first (no network); falls back to INSTALL + LOAD on version mismatch.
ddb_connect <- function(path = ":memory:", remote = FALSE, read_only = FALSE) {
drv <- duckdb::duckdb(dbdir = path, read_only = read_only)
# Keep driver in globalenv so R's GC never collects it before the connection
# is closed. parent.frame() is unreliable when called through source()/eval()
# chains (returns a temporary env that is GC'd immediately).
assign(".ddb_drv", drv, envir = globalenv())
con <- DBI::dbConnect(drv)
tryCatch(
DBI::dbExecute(con, "LOAD spatial"),
error = function(e) {
DBI::dbExecute(con, "INSTALL spatial")
DBI::dbExecute(con, "LOAD spatial")
}
)
if (remote) {
tryCatch(
DBI::dbExecute(con, "LOAD httpfs"),
error = function(e) {
DBI::dbExecute(con, "INSTALL httpfs")
DBI::dbExecute(con, "LOAD httpfs")
}
)
}
con
}
# Convert sf geometry column to WKB blob for DuckDB insert
sf_to_wkb_df <- function(sf_obj) {
wkt <- sf::st_as_text(sf::st_geometry(sf_obj))
df <- sf::st_drop_geometry(sf_obj)
df$geom_wkt <- wkt
df
}
# Read WKB blob column back to sf
# DuckDB returns ST_AsWKB as a list of raw vectors β€” st_as_sfc accepts it directly
wkb_to_sf <- function(df, geom_col = "geom", crs = 4326) {
geoms <- sf::st_as_sfc(df[[geom_col]], crs = crs)
df[[geom_col]] <- NULL
sf::st_as_sf(df, geometry = geoms)
}
# Stat display helper for Shiny summary panel
stat_row <- function(label, value) {
htmltools::tags$div(
class = "d-flex justify-content-between small py-1 border-bottom border-secondary",
htmltools::tags$span(class = "text-muted", label),
htmltools::tags$span(class = "fw-semibold", value)
)
}