## 'data.frame':    32 obs. of  11 variables:
##  $ mpg : num  21 21 22.8 21.4 18.7 18.1 14.3 24.4 22.8 19.2 ...
##  $ cyl : num  6 6 4 6 8 6 8 4 4 6 ...
##  $ disp: num  160 160 108 258 360 ...
##  $ hp  : num  110 110 93 110 175 105 245 62 95 123 ...
##  $ drat: num  3.9 3.9 3.85 3.08 3.15 2.76 3.21 3.69 3.92 3.92 ...
##  $ wt  : num  2.62 2.88 2.32 3.21 3.44 ...
##  $ qsec: num  16.5 17 18.6 19.4 17 ...
##  $ vs  : num  0 0 1 1 0 1 0 1 1 1 ...
##  $ am  : num  1 1 1 0 0 0 0 0 0 0 ...
##  $ gear: num  4 4 4 3 3 3 3 4 4 4 ...
##  $ carb: num  4 4 1 1 2 1 4 2 2 4 ...

This notebook walks through writing two functions end to end: a hand-built median() and a parameterized ggplot2 function. Run every chunk in order — nothing here depends on unseen setup.

1. Minimum viable function

## [1] 8

return() is optional — R returns the last evaluated expression regardless:

## [1] 12

Keep return() for early exits or readability; it costs nothing and documents intent.

2. Rebuild median()

## [1] 19.2
## [1] 19.2

identical(get_median(mtcars$mpg), median(mtcars$mpg)) returns TRUE for this vector. mtcars$mpg has 32 values (even), so the function sorts and averages positions 16 and 17 — both 19.2 here, which is why the manual and base results align exactly rather than approximately.

Quick check on an odd-length vector to confirm the other branch:

## [1] 4

Sorted: 1, 2, 4, 7, 9 — middle value is 4, matching median(c(4,1,7,2,9)).

3. A tidy-eval ggplot2 function

Inspect the summary table the function builds before it plots anything:

## # A tibble: 3 × 3
##     cyl mean_val se_val
##   <dbl>    <dbl>  <dbl>
## 1     4     26.7  1.36 
## 2     6     19.7  0.549
## 3     8     15.1  0.684

(bar chart: 3 bars — 4cyl ≈26.7, 6cyl ≈19.7, 8cyl ≈15.1 — with SE error bars, theme_minimal)

Swap datasets without touching the function body:

4. Why {{ }} is not optional here

Without curly-curly, group_by({{ group_var }}) would fail or silently misbehave when group_var is passed as a bare column name, because group_by() expects an expression, not the string/symbol ambiguity a plain function argument creates. {{ }} tells dplyr to evaluate group_var in the caller’s data context. Try removing it and re-running — you’ll get object 'cyl' not found even though cyl is a real column in mtcars, because R is looking for a variable named cyl in the function’s own environment, not in data.

5. Four extension points

## [1] "Hello, Guest"

## [1] FALSE
## [1]  2  4  6  8 10

Session info

## R version 4.5.1 (2025-06-13 ucrt)
## Platform: x86_64-w64-mingw32/x64
## Running under: Windows 10 x64 (build 19045)
## 
## Matrix products: default
##   LAPACK version 3.12.1
## 
## locale:
## [1] LC_COLLATE=English_United States.utf8 
## [2] LC_CTYPE=English_United States.utf8   
## [3] LC_MONETARY=English_United States.utf8
## [4] LC_NUMERIC=C                          
## [5] LC_TIME=English_United States.utf8    
## 
## time zone: Asia/Karachi
## tzcode source: internal
## 
## attached base packages:
## [1] stats     graphics  grDevices utils     datasets  methods   base     
## 
## other attached packages:
## [1] ggplot2_4.0.1 dplyr_1.1.4  
## 
## loaded via a namespace (and not attached):
##  [1] vctrs_0.6.5        cli_3.6.5          knitr_1.51         rlang_1.1.6       
##  [5] xfun_0.56          otel_0.2.0         generics_0.1.4     S7_0.2.1          
##  [9] jsonlite_2.0.0     labeling_0.4.3     glue_1.8.0         htmltools_0.5.9   
## [13] sass_0.4.10        scales_1.4.0       rmarkdown_2.30     grid_4.5.1        
## [17] evaluate_1.0.5     jquerylib_0.1.4    tibble_3.3.0       fastmap_1.2.0     
## [21] yaml_2.3.12        lifecycle_1.0.5    compiler_4.5.1     RColorBrewer_1.1-3
## [25] pkgconfig_2.0.3    rstudioapi_0.18.0  farver_2.1.2       digest_0.6.39     
## [29] R6_2.6.1           tidyselect_1.2.1   pillar_1.11.1      magrittr_2.0.4    
## [33] bslib_0.10.0       withr_3.0.2        gtable_0.3.6       tools_4.5.1       
## [37] cachem_1.1.0

Full narrative version with a mistakes checklist and FAQ: https://www.rstudiodatalab.com/2026/09/create-function-in-r-custom-examples.html