layout: true --- ## Shiny apps > Shiny is an R package that makes it easy to build interactive web apps straight from R. You can host standalone apps on a webpage or embed them in R Markdown documents or build dashboards. You can also extend your Shiny apps with CSS themes, htmlwidgets, and JavaScript actions. https://shiny.rstudio.com/ --- class: middle ## Example 1: Movie Explorer .center[https://shiny.rstudio.com/gallery/movie-explorer.html] --- class: middle ## Example 2: CRAN explorer .center[https://gallery.shinyapps.io/cran-explorer/] --- ## Why Use Shiny? - Build interactive applications using only R - Enables data exploration with dynamic UI - Deployable as dashboards or embedded in reports - Popular in health, public sector, finance, academia --- ## Anatomy of a Shiny App Every Shiny app has 3 key parts: - .highlight[UI] (user interface) - .highlight[Server] (logic + reactivity) - .highlight[Input/output bindings] – Links user actions (**ui**) and app responses (**server**) --- ## Let’s explore a simple Shiny interaction Pick a number ``` r library(shiny) # UI element sliderInput("num", "Pick a number", min = 1, max = 100, value = 50) ```
Pick a number
Result (reactive output) ``` r # Output definition renderText({ paste("Double of your number is:", input$num * 2) }) ```
--- ## Key Concepts in Shiny: - Reactive .highlight[Inputs]: Values from widgets like sliders, text boxes, select menus - Reactive .highlight[Outputs]: renderText, renderPlot, renderTable, etc. - Reactive .highlight[Expressions]: Efficient computations that depend on inputs --- ## Shiny Front-End Anatomy: UI Layout - `fluidPage()`: most basic layout - rows containing columns - rows making sure elements appear on the same line - UI input: Logic: Widget = Web element the user can interact with [Shiny widget gallery](https://shiny.posit.co/r/gallery/widgets/widget-gallery/) --- ### Try this code in your console for a simple UI ``` r library(shiny) # UI layout ui <- fluidPage( titlePanel("Fancy App"), sidebarLayout( # Sidebar panel sidebarPanel( h4("Sidebar"), p("Use this space for inputs like sliders, selectors, or buttons.") ), # Main panel for outputs and content mainPanel( h4("Main Content"), # 3 columns fluidRow( column(4, h5("Description"), p("This area is for explaining what the app does.") ), column(4, h5("Model Output"), p("Use this section to show summaries, tables, or results.") ), column(4, h5("Visualization"), p("Render plots or graphics here.") ) ) ) ) ) # Server logic placeholder server <- function(input, output, session) { # This is where server-side reactivity will go } # Run the app shinyApp(ui = ui, server = server) ```
--- ## Loading and Exploring the Flights Dataset We’ll use `nycflights13::flights` for a real-world example. ``` r library(nycflights13) library(dplyr) library(ggplot2) head(flights) ``` ``` ## # A tibble: 6 × 20 ## year month day dep_time sched_dep_time dep_delay arr_time ## <int> <int> <int> <int> <int> <dbl> <int> ## 1 2013 1 1 517 515 2 830 ## 2 2013 1 1 533 529 4 850 ## 3 2013 1 1 542 540 2 923 ## 4 2013 1 1 544 545 -1 1004 ## 5 2013 1 1 554 600 -6 812 ## 6 2013 1 1 554 558 -4 740 ## # ℹ 13 more variables: sched_arr_time <int>, arr_delay <dbl>, ## # carrier <chr>, flight <int>, tailnum <chr>, origin <chr>, ## # dest <chr>, air_time <dbl>, distance <dbl>, hour <dbl>, ## # minute <dbl>, time_hour <dttm>, date <date> ``` --- ## Filter Flights from JFK in January ``` r flights %>% filter(origin == "JFK", month == 1) %>% group_by(carrier) %>% summarise(mean_arr_delay = mean(arr_delay, na.rm = TRUE)) %>% arrange(desc(mean_arr_delay)) ``` ``` ## # A tibble: 10 × 2 ## carrier mean_arr_delay ## <chr> <dbl> ## 1 HA 27.5 ## 2 EV 12.7 ## 3 9E 9.72 ## 4 MQ 7.02 ## 5 US 4.99 ## 6 B6 3.39 ## 7 AA 0.507 ## 8 UA -0.223 ## 9 DL -9.86 ## 10 VX -15.3 ``` --- ## TASK 1: Data Wrangling Warm-up (10 min) Use dplyr to answer: - Which carrier has the longest average arrival delay? - What is the shortest average air time from LGA? --- ## Interactive Carrier Selection Select a carrier below to view data: ``` r selectInput("carrier_sel", "Choose a carrier:", choices = unique(flights$carrier)) ```
Choose a carrier:
UA
AA
B6
DL
EV
MQ
US
WN
VX
FL
AS
9E
F9
HA
YV
OO
Summary Statistics ``` r renderPrint({ req(input$carrier_sel) flights %>% filter(carrier == input$carrier_sel) %>% summarise( mean_delay = mean(arr_delay, na.rm = TRUE), sd_delay = sd(arr_delay, na.rm = TRUE), flights = n() ) }) ```
--- ## Visualize Delays by Carrier ``` r renderPlot({ req(input$carrier_sel) flights %>% filter(carrier == input$carrier_sel) %>% ggplot(aes(x = arr_delay)) + geom_histogram(binwidth = 5, fill = "#0073C2FF", color = "white") + xlim(-50, 200) + labs(title = paste("Arrival Delay for", input$carrier_sel), x = "Arrival Delay (min)", y = "Count") }) ```
--- ## Add Origin Selection to the Filter ``` r selectInput("origin_sel", "Choose origin airport:", choices = unique(flights$origin)) ```
Choose origin airport:
EWR
LGA
JFK
``` r renderPlot({ req(input$carrier_sel, input$origin_sel) flights %>% filter(carrier == input$carrier_sel, origin == input$origin_sel) %>% ggplot(aes(x = arr_delay)) + geom_histogram(binwidth = 5, fill = "#D55E00", color = "white") + labs(title = paste("Delays for", input$carrier_sel, "from", input$origin_sel), x = "Arrival Delay (min)", y = "Count") }) ```
--- ## TASK 2: Multi-Input Filtering (15 min) Add to the existing app: - A date filter (hint: use `lubridate::make_date`(year, month, day)) - A scatterplot of `dep_delay` vs. `arr_delay` with color = destination --- ## Let's add a Date Range Input ``` r dateRangeInput("date_range", "Select date range:", start = "2013-01-01", end = "2013-01-31") ```
Select date range:
to
``` r renderPlot({ req(input$carrier_sel, input$date_range) flights %>% filter(carrier == input$carrier_sel) %>% mutate(date = as.Date(time_hour)) %>% filter(date >= input$date_range[1], date <= input$date_range[2]) %>% ggplot(aes(x = dep_delay, y = arr_delay, color = dest)) + geom_point(alpha = 0.5) + labs(title = "Departure vs. Arrival Delay", x = "Departure Delay", y = "Arrival Delay") }) ```
--- ## TASK 3: Build Your Own Mini Dashboard (30 min) - Choose an aspect of the flights dataset to explore - Design at least two inputs and two outputs - Add interactivity (e.g. filtering, comparison, visualization) --- ## Common Mistakes & Debugging Tips - Forgetting `req()` before using an input - Mixing up `render*` and `output$*` - Not wrapping logic inside `reactive()` or render blocks - Visuals not appearing? Check for missing `outputId` or input dependencies --- ## Deployment Options - shinyapps.io : official, free tier available - Shiny Server (on-premise or cloud) - Use flexdashboard + runtime: shiny for inline web reports --- ## Resources: Online courses & tutorials - Overview of resources - [*learnR4free*](https://www.learnr4free.com/) by Mine Dogucu - the [*Big Book of R*](https://www.bigbookofr.com/) by Oscar Baruffa - [*swirl* - Learn `R` in `R`](https://swirlstats.com/) - Learning `R` (and statistics) with a cute story: [Teacups, Giraffes, & Statistics by Hasse Wallum & Desirée de Leon](https://tinystats.github.io/teacups-giraffes-and-statistics/) --- ## Working with text data in `R` As with almost everything else, there are many great resources for working with text data in `R`. Two good options (and starting points) are: - the [`tidytext` package](https://juliasilge.github.io/tidytext/) and the "accompanying" book [*Text Mining with R: A Tidy Approach*](https://www.tidytextmining.com/) by Julia Silge & David Robinson - the [`quanteda` package](https://quanteda.io/) and its accompanying [tutorials](https://tutorials.quanteda.io/) - a nice and free self-paced online course is [*Text mining in R for the social sciences and digital humanities*](https://tm4ss.github.io/docs/index.html) by Andreas Niekler and Gregor Wiedemann --- ## 'Web development' using `R` These days, a lot of `R` packages provide tools originally developed for the web. For example: - [bookdown](https://pkgs.rstudio.com/bookdown/) enables you to publish books written in `R Markdown` online - [pkgdown](https://pkgdown.r-lib.org/) does the same for your own `R` packages - [blogdown](https://pkgs.rstudio.com/blogdown/l) is more general and helps you with creating websites (examples to follow) --- ## Writing your own `R` packages .pull-left[ At a certain point (not now!), you may want to consider writing your own `R` package - useful for creating reproducible code - great for distributing your work to others ] .pull-right[ <img src="data:image/png;base64,#../img/r_packages.jpg" width="1381" style="display: block; margin: auto;" /> [Read the book here!](https://r-pkgs.org/) ] --- class: middle ## It's straightforward in `RStudio` <img src="data:image/png;base64,#../img/new_package.png" width="75%" style="display: block; margin: auto;" /> --- ## Acknowledgements ❤️ All slides were created with the `R` package [`xaringan`](https://github.com/yihui/xaringan) which builds on [`remark.js`](https://remarkjs.com), [`knitr`](http://yihui.name/knitr), and [`R Markdown`](https://rmarkdown.rstudio.com). The exercises were created with the [`unilur` package](https://github.com/koncina/unilur). [`woRkshoptools`](https://stefanjuenger.github.io/woRkshoptools/)