map_dfr() row-binds data frame results — ideal for simulation replicates or per-group outputs.
set.seed(7) # reproducible drawssp <-unique(reef$species) # species labelssim <-map_dfr(sp, function(s) { # one df per speciestibble(species = s, draw =rpois(3, lambda =5)) # three random counts})sim # stacked draws
walk() maps for side effects such as messages or file writes and discards return values.
walk(names(by_site), function(nm) { # iterate site namesmessage("Site: ", nm, " — rows: ", nrow(by_site[[nm]])) # logging side effect})invisible(NULL) # walk returns input invisibly
Q9 · reduce() combine lists
reduce() folds a list with a binary function — combine vectors or merge tables stepwise.
by_an <-split(acoustic$detections, acoustic$animal_id) # list of numsper_an <-map_dbl(by_an, sum) # one total per animal tagtotal_det <-reduce(per_an, `+`) # fold scalar sums togethertotal_det # grand total detections
[1] 91
Q10 · list-columns intro
Tibbles can store list-columns — each cell holds a vector or mini data frame before unnest().
nested_bio <- biolog |># biologging tablegroup_by(burst_id) |># one row per burst soonsummarise(times =list(seconds), depths =list(depth_m), .groups ="drop")nested_bio # list-columns visible
map2() on paired vectors supports weighted calculations — tonnes times price, detections times effort.
x <- biolog$depth_m[1:10] # depths subsamplew <-rep(1, 10) # equal weights demoweighted <-map2_dbl(x, w, ~ .x * .y) # element productssum(weighted) /sum(w) # weighted mean depth
[1] 4.941123
Q14 · possibly() softer failures
possibly() replaces errors with a default value — softer than safely() when you want NA back.
mult <-c(1, 2, 0, 4) # includes zero divisorsafe_div <-possibly(function(a, b) a / b, otherwise =NA_real_)map2_dbl(acoustic$detections[1:4], mult, safe_div) # NA where divide fails
[1] 5 1 Inf 1
Q15 · quietly() hide messages
quietly() captures messages while returning results — useful when mapped functions are chatty.
chatty_mean <-function(x) { # function with messagemessage("computing mean on length ", length(x))mean(x)}q <-quietly(chatty_mean) # wrap to capture noiseres <-map(by_site, ~q(.x$count)) # list of quiet resultsmap_dbl(res, "result") # extract means only
East North South
10.95 8.80 9.80
Q16 · furrr parallel map
furrrfuture_map() mirrors map() on parallel workers — worth it on heavy simulations, not tiny reef tables.
has_furrr <-requireNamespace("furrr", quietly =TRUE) # check packageif (has_furrr) {suppressPackageStartupMessages({ library(furrr); library(future) })plan(multisession, workers =2) # local worker poolfuture_map_dbl(by_site, ~mean(.x$count)) # parallel map} else {message("Install furrr for parallel demo; using map_dbl")map_dbl(by_site, ~mean(.x$count)) # serial fallback}
East North South
10.95 8.80 9.80
Q17 · future plans & workers
The futureplan() selects sequential vs multisession execution — set once before furrr maps.
time_serial <-system.time({ # time serial mapmap_dbl(by_site, ~mean(.x$count))})time_serial # print timing object
user system elapsed
0.001 0.000 0.000
Q18 · map deep on biologging
Map over burst splits to build hierarchical summaries — ‘deep’ mapping across nested structure.
burst_stats <- biolog |># biologging datagroup_split(burst_id) |># list of burst tibblesmap(~summarise(.x, mean_depth =mean(depth_m), n_sec =n()))burst_tbl <-map_dfr(burst_stats, identity) # row-bind summarieshead(burst_tbl) # one row per burst
Integrate split, map, and map_dfr() on acoustic data — the workflow to verify before batch-processing receiver exports with AI.
zone_list <-group_split(acoustic, reef_zone) # list by habitat zonezone_summary <-map_dfr(zone_list, function(df) {tibble(reef_zone =unique(df$reef_zone),total_det =sum(df$detections),n_rows =nrow(df) )})ggplot(zone_summary, aes(x = reef_zone, y = total_det, fill = reef_zone)) +geom_col(show.legend =FALSE) +# bar chart by zonelabs(title ="Detections by reef zone", y ="Sum of detections")