Sign in

Simon Smart

@simonsmart.bsky.social
216 followers 267 following 119 posts

✨ Research Software Engineer at University of Birmingham 🥔 Former spudologist 🌱 Grows plants 🚲 Rides bikes 🍺 Brews beer 🌐 github.com/simon-smart88

PostsRepliesMedia
Simon Smart @simonsmart.bsky.social · 09/09/2026
#rstats When you have a choice of characters as a parameter to a function, how should the choices be formatted in the docs? I have previously used option A without ever checking what the "correct" way is. 1/3
3 options for formatting:

character. Outcome type for the dataset. Either `binary` or `continuous`.
character. Outcome type for the dataset. Either "binary" or "continuous".
character. Outcome type for the dataset. Either `"binary"` or `"continuous"`.
250
Simon Smart @simonsmart.bsky.social · 18/06/2026
As a side-effect we also created a way to conduct a variety of NMAs through a simple API without using the app. Once the data is configured, you can generate some outputs or pass the data to a model function and use the result to generate more outputs. 4/5
configured_data <- setup_load("my_data.csv", outcome = "continuous") |>
  setup_configure(reference_treatment = "Placebo",
                  effects = "random",
                  outcome_measure = "MD",
                  ranking_option = "good",
                  seed = 123)
freq_forest(configured_data) |> 
  write_plot("frequentist_forest_plot.pdf")

bayes_model(configured_data) |> 
  bayes_forest() |>
  write_plot("bayesian_forest_plot.pdf")
120
Simon Smart @simonsmart.bsky.social · 18/06/2026
It was already one of the most impactful academic shiny apps with > 400 citations, but this update makes it reproducible using {shinyscholar}. Whatever you do in the app, you can download a Quarto document that reproduces every step or render it to produce an html report. 2/5
Example Quarto and html reports produced by the app
111
Simon Smart @simonsmart.bsky.social · 18/06/2026
Metainsight is now available on CRAN! cran.r-project.org/package=meta... It is a shiny app for conducting network meta-analysis, which in simple terms, is used by doctors to decide which of multiple treatments is best to treat your ailments. #rstats #metaanalysis #openscience 1/5
A screenshot of the app running show options in the sidebar and two forest plots displayed side by side
161
Simon Smart @simonsmart.bsky.social · 13/06/2026
Saturday meetings aren't great but can't get a much better venue to chat about #rstats
000
Simon Smart @simonsmart.bsky.social · 26/03/2026
I’m giving a seminar on 20th April about refactoring crsu.shinyapps.io/MetaInsight/ to use {shinyscholar}, producing crsu.shinyapps.io/MetaInsight_... Details and sign up: www.eventbrite.co.uk/e/crsu-webin... A shorter version is also coming to R/Medicine in May #rstats #metaanalysis #openscience
Poster for the seminar: MetaInsight v7: Making a comprehensive app for network meta analysis reproducible
002
Simon Smart @simonsmart.bsky.social · 05/03/2026
Partial matching of names in #rstats is wild. I knew the function would run, but didn't know it "works" with dataframes as well!
f <- function(very_fast, 
              incredibly_dangerous){
  data.frame("very_fast" = 
             very_fast, 
             "incredibly_dangerous" = 
             incredibly_dangerous)
}

df <- f(v = 1, i = 2)
df$very * df$inc
df$very_broken <- 3
df$very * df$inc
341
Simon Smart @simonsmart.bsky.social · 10/02/2026
Is there a term for figuring something out that LLMs say isn't possible? Grind coding? Organic coding? In this case, rendering <text> elements in an SVG to <path> in #Rstats. (Claude cooked up a whole non-functioning package in an attempt to do it).
'<svg><text x="0" y="200" 
style="font-size: 100px;">
Hello world</text></svg>' |>
charToRaw() |>
rsvg::rsvg_svg(NULL) |>
rawToChar()
010
Simon Smart @simonsmart.bsky.social · 20/10/2025
#rstats when I run devtools::test() from the Build pane I get an error that mirai isn't installed even though it is. I use r2u and have already uninstalled with apt remove and reinstalled. It runs okay from the terminal but whatever environment shinytest2 runs in can't find mirai either. Any ideas?
==> devtools::test()

ℹ Testing metainsight
Error in load_imports(path) : The package "mirai" is required.
Calls: <Anonymous> ... load_imports -> deps_check_installed -> check_installed
Execution halted

Exited with status 1.
210
Simon Smart @simonsmart.bsky.social · 21/08/2025
I've made digital art using .svgs for many years and inspired by #rtistry I've made a #rstats #rshiny app which generates them: simonsmart.shinyapps.io/savage-patte... the video shows some example outputs.
1134
Simon Smart @simonsmart.bsky.social · 21/07/2025
Myself and @statsforbios.bsky.social are running a workshop in September to introduce Disagapp disagapp.le.ac.uk for disaggregation regression. More details and sign up at forms.office.com/e/pjfbD6RvTi #rstats #episky #AcademicSky
Disaggregation regression produces high resolution predictions from data aggregated into polygons making it well suited to epidemiological modelling. Disagapp makes the process simple and easy! 

Join Simon Smart and Tim Lucas for this introductory workshop.

On Teams 14:00-16:00 UTC  16 September 2025 

See more details and sign up via the QR code
072
Simon Smart @simonsmart.bsky.social · 29/04/2025
Being able to cancel and restart slow-running jobs in shiny with {mirai} is a bit of a game-changer #rstats Full app in alt text / gist.github.com/simon-smart8... with a method for updating progress too
library(shiny)
library(bslib)
library(mirai)

daemons(1)
onStop(function() daemons(0))

ui <- page_fluid(
  p("The time is ", textOutput("current_time", inline = TRUE)),
  hr(),
  numericInput("n", "Sample size (n)", 100),
  numericInput("delay", "Seconds to take for plot", 5),
  actionButton("btn", "Go"),
  textOutput("progress_log"),
  plotOutput("plot"),
)

my_func <- function(x, y, file){
  writeLines(paste0("Starting..."), file)
  for (i in 1:y){
    Sys.sleep(1)
    writeLines(paste0("Step ", i, " complete"), file)
  }
  writeLines(paste0("Finished"), file)
  runif(x)
}

server <- function(input, output, session) {

  progress_file <- tempfile()

  output$current_time <- renderText({
    invalidateLater(1000)
    format(Sys.time(), "%H:%M:%S %p")
  })

  task_var <- NULL
  task <- ExtendedTask$new(
    function(...) task_var <<- mirai(run(...), environment(), .args = list(run = my_func))
  )

  observeEvent(input$btn, {
    if (task$status() == "running"){
      mirai::stop_mirai(task_var)
    }
    task$invoke(input$n, input$delay, progress_file)}
  )

  output$plot <- renderPlot({
    if (task$status() == "success"){
      hist(task$result())
    }
  })

  progress_reader <- reactiveFileReader(100, session, progress_file,
                                        readFunc = function(file) {
                                          if (file.exists(file)) {
                                            readLines(file)
                                          }
                                        }
  )

  output$progress_log <- renderPrint({
    cat(paste(progress_reader(), collapse = "\n"))
  })

}

shinyApp(ui = ui, server = server)
1114
Simon Smart @simonsmart.bsky.social · 10/02/2025
create_template() makes a skeleton application composed of shiny modules that can optionally contain a datatable, leaflet map and display source code. Each module calls one function and suits am Rmd-first approach to development, that also minimises reactivity and opens functionality to testing.
Flowchart of the suggested workflow for developing modules, prototyped in an rmarkwdown, transferred to a function, unit tests written, develop the shiny module, reproduce the module in rmarkdown and then write end-to-end tests.
200
Simon Smart @simonsmart.bsky.social · 10/02/2025
Looking at fifty academic shiny apps published in 2023 we found that few of them had the same features and many displayed sub-optimal standards in software development. Some apps had thousands of lines of code in a single file and testing was very rare.
A graph showing the proportion of academic apps published in 2023 that cite packages, are deployed, provide instructions, provide logging, are reproducible, can be saved and loaded, are open source, include functions, are modular, are packaged and include unit and end-to-end tests.
151
Simon Smart @simonsmart.bsky.social · 10/02/2025
It shouldn’t be necessary to have read a user guide or watch a video to use an app and so shinyscholar apps provide guidance users on how to use each module as well as the scientific basis of the module.
A screenshot of the module guidance documentation inside the demonstration app.
110
Simon Smart @simonsmart.bsky.social · 10/02/2025
Once a user has conducted an analysis they can download an rmarkdown document that replicates all the steps. In addition, apps made with shinyscholar can be saved and loaded, have a flexible logging system, support asynchronous operations and attribute package developers.
A screenshot of an rmarkdown document reproducing an analysis in shinyscholar
112
Simon Smart @simonsmart.bsky.social · 10/02/2025
My first R package is now available on CRAN! Shinyscholar is a template for creating complex analytical applications that are reproducible outside the application. 🧵 cran.r-project.org/web/packages... #rstats #rshiny #openscience
A screenshot of an R shiny application created by shinyscholar, with user inputs on the left sidebar, a tab panel to move between components and a main panel featuring a map, table and results.
2187
Simon Smart @simonsmart.bsky.social · 06/12/2024
Day 6 part 1 of #adventofcode in #Rstats. I learnt from day 4 and padded the input from the start which made it a lot simpler. Barely any use of apply which makes a change from so far.
020
Simon Smart @simonsmart.bsky.social · 05/12/2024
Day 5 part 2 of #adventofcode in base #Rstats. This took forever to work out until I realised I could always put the first wrong element at the end
170
Simon Smart @simonsmart.bsky.social · 05/12/2024
Just in time for Day 5 part 1 of #adventofcode in base #Rstats. Not super pleased with this and I'm sure there is some room for improvement, but it works.
060
Simon Smart @simonsmart.bsky.social · 04/12/2024
And part 2 which was pretty simple to adapt from part 1
000
Simon Smart @simonsmart.bsky.social · 04/12/2024
Day 4 part 1 of #adventofcode in base #Rstats. This was a whole lot easier once the input was padded. I was surprised there is no function equivalent to rdrr.io/cran/terra/m... for a matrix (or is there?)
291
Simon Smart @simonsmart.bsky.social · 04/12/2024
Day 3 of #adventofcode in base #Rstats and I managed to write some regex all by myself!
090
Simon Smart @simonsmart.bsky.social · 02/12/2024
I see. I went with this so it was natural to use it for both, but your solution does prevent checking the diff unnecessarily. Do you need the double || ? Thought that was just if one could be NULL
220