Carregant...
 
6 de maig de 2024 - Creació d'Aplicacions Interactives amb servidor Shiny i mostrar projecte

Creació d'Aplicacions Interactives amb servidor Shiny

Curs R Avançat Equips - Sessió 5

Avui

Creació d'Aplicacions Interactives amb servidor Shiny, i conèixer l'existència d'algunes les altres opcions en R també.

1. Introducció a R Shiny

Aplicacions dinàmiques i interactives, amb components reactius, que requereixen de servidor shiny on col.locar les aplicacions.


Veure alguna aplicació feta amb Shiny (requereix servidor de R i de Shiny), del tipus:


Treball pràctic de creació d’un dashboard amb Shiny i modificació.
Es pot aprendre com fer-ne apps Shiny, a poc a poc, a través de:
https://mastering-shiny.org/basic-app.html

Es pot començar emprant una plantilla base que proporciona RStudio en fer un projecte nou de tipus Shiny App:

  • File > New Project > New Directory > Shiny Web Application
    240421 RStudio NewProject New Shiny Web App 00


O si es vol afegir dins un projecte de RStudio pre-existent:

  • File > New File > Shiny Web App > New Shiny Web Application.
    240421 RStudio File New Shiny Web App 00


O es pot emprar una plantilla base a través del ShinyUIEditor, que empra a la seva vegada una disposició versàtil de tipus gridlayout
Build Shiny application UIs by dragging-and-dropping. Generates clean and proper code as you build.

1.1. Estructura d'una app shiny

En crear una app shiny a partir d'un arxiu nou dins un projecte de Rstudio pre-existent, se'ns crea aquest arxiu app.R:

Contingut de l'arxiu app.R
51
 
1
#
2
# This is a Shiny web application. You can run the application by clicking
3
# the 'Run App' button above.
4
#
5
# Find out more about building applications with Shiny here:
6
#
7
#    http://shiny.rstudio.com/
8
#
9
10
library(shiny)
11
12
# Define UI for application that draws a histogram
13
ui <- fluidPage(
14
15
    # Application title
16
    titlePanel("Old Faithful Geyser Data"),
17
18
    # Sidebar with a slider input for number of bins 
19
    sidebarLayout(
20
        sidebarPanel(
21
            sliderInput("bins",
22
                        "Number of bins:",
23
                        min = 1,
24
                        max = 50,
25
                        value = 30)
26
        ),
27
28
        # Show a plot of the generated distribution
29
        mainPanel(
30
           plotOutput("distPlot")
31
        )
32
    )
33
)
34
35
# Define server logic required to draw a histogram
36
server <- function(input, output) {
37
38
    output$distPlot <- renderPlot({
39
        # generate bins based on input$bins from ui.R
40
        x    <- faithful[, 2]
41
        bins <- seq(min(x), max(x), length.out = input$bins + 1)
42
43
        # draw the histogram with the specified number of bins
44
        hist(x, breaks = bins, col = 'darkgray', border = 'white',
45
             xlab = 'Waiting time to next eruption (in mins)',
46
             main = 'Histogram of waiting times')
47
    })
48
}
49
50
# Run the application 
51
shinyApp(ui = ui, server = server)


En clicar al botó de "RunApp" se'ns aixeca una finestra emergent amb aquest contingut:

240421 RStudio File New Shiny Web App 01


A partir d'aquí, podríem anar retocant el codi de l'app.R per fer evolucionar la app.

O bé, podem començar a partir del shinyuieditor, que ens permetrà començar ja amb una interfícies shiny molt més avançada per ajustar-se al que volíem per a la nostra app Shiny.

1.2. ShinyUIEditor

https://rstudio.github.io/shinyuieditor/

1.3. App demo shiny-sales-de-joc

S'ha creat una app demo de shiny, emprant les plantilles de shinyuieditor.

Per crear-ho des de zero, executem aquest tipus de comanda primera vegada:

1
 
1
shinyuieditor::launch_editor(app_loc=file.path("sessio_05", "shiny-sales-de-joc"))


Això ens obrirà una finestra del navegador en que hi haurà l'aplicació d'edició gràfica d'interfícies d'usuari d'aplicacions shiny (shinyuieditor)

240421 Shinyuieditor Sales De Joc 02

Escollim quina plantilla volem agafar de partida (per exemple, "Grid Geyser"), i cliquem al botó "Next" de sota a l'esquerra.
Llavors ja podem fer els canvis que necessitem a la nostra interfície.

240421 Shinyuieditor Sales De Joc 03

En quant tanquem la finestra del navegador on hi havia el shinyuieditor, ens trobarem que tenim actualitzat l'arxiu "app.R" a la carpeta que havíem indicat inicialment, amb el codi actualitzat necessari per produir aquesta interfície d'usuari de Shiny.

240421 Shinyuieditor Sales De Joc 04 Editada

Ara podem continuar canviant els conjunts de dades que venen per omissió sobre geishers (dataframe "faithful" al codi), i les columnes/variables d'interès, per les nostres.
I associar els elements nous de dades (dins la funció server() ) als controls de la interfície que calgui, per adaptar la nostra nova aplicació shiny a les nostres necessitats.

240421 Shinyuieditor Sales De Joc 05

Contingut de app.R
180
 
1
library(shiny)
2
library(plotly)
3
library(gridlayout)
4
library(bslib)
5
library(DT)
6
library(sf)
7
library(readxl)
8
library(dplyr)
9
library(stringr)
10
library(janitor)
11
library(leaflet)
12
library(leaflet.providers)
13
14
ui <- grid_page(
15
  layout = c(
16
    "header  header     indicator ",
17
    "sidebar sidebar    plotly  ",
18
    "table   table      mymap   ",
19
    "table   table      mymap   "
20
  ),
21
  row_sizes = c(
22
    "120px",
23
    "1.5fr",
24
    "1fr",
25
    "1fr"
26
  ),
27
  col_sizes = c(
28
    "290px",
29
    "0.59fr",
30
    "1.41fr"
31
  ),
32
  gap_size = "1rem",
33
  grid_card(
34
    area = "sidebar",
35
#    card_header("Paràmetres"),
36
    card_body(
37
      selectInput(
38
        inputId = "myProvincies",
39
        label = "Província",
40
        choices = list(
41
          "BCN" = "Barcelona",
42
          "GRN" = "Girona",
43
          "LLD" = "Lleida",
44
          "TCN" = "Tarragona"
45
        ),
46
        selected = "Barcelona"
47
      ),
48
      sliderInput(
49
        inputId = "myradius",
50
        label = "Mida dels punts al mapa",
51
        min = 1,
52
        max = 10,
53
        value = 3,
54
        width = "100%"
55
      ),
56
      numericInput(
57
        inputId = "numRows",
58
        label = "Nombre de files de la taula",
59
        value = 5,
60
        min = 1,
61
        step = 1,
62
        width = "100%"
63
      )
64
    )
65
  ),
66
  grid_card_text(
67
    area = "header",
68
    content = "Sales de joc de Catalunya",
69
    alignment = "start",
70
    is_title = FALSE
71
  ),
72
  grid_card(
73
    area = "table",
74
    card_header("Table"),
75
    card_body(DTOutput(outputId = "myTable", width = "100%"))
76
  ),
77
  grid_card(
78
    area = "mymap",
79
    card_body(leafletOutput("mymap"))
80
  ),
81
  grid_card(
82
    area = "indicator",
83
#    card_header("Nombre de Sales de Joc"),
84
    card_body(
85
      value_box(
86
        title = "Registres",
87
        value = textOutput(outputId = "indicator"),
88
        showcase = bsicons::bs_icon("database")
89
      )
90
    )
91
  ),
92
  grid_card(
93
    area = "plotly",
94
    card_header("Sales per municipi"),
95
    card_body(
96
      plotlyOutput(
97
        outputId = "distPlot",
98
        width = "100%",
99
        height = "100%"
100
      )
101
    )
102
  )
103
)
104
105
106
server <- function(input, output) {
107
  
108
  # Carreguem les dades dins una expressió reactiva (només s'executa una vegada, fins que canviïn les dades)  
109
  # Importa les dades
110
  dataset <- reactive({
111
    muni_cat <- rio::import(file.path("..", "muni_cat.csv"))
112
    
113
    st_as_sf(
114
      read_xlsx(file.path("..", "..", "curs-r-avancat-equips", "sessio_02", "salons_de_joc_en_la_web.xlsx")),
115
      coords = c("longitud", "latitud"), crs = 4326, agr = "constant"
116
    ) %>% # Retoquem noms per a que encaixin tots al join de sota
117
    mutate(
118
        nom_municipi = case_when(
119
          cp == "08904" ~ "Cornellà de Llobregat",
120
          TRUE ~ nom_municipi),
121
        nom_municipi = str_replace_all(nom_municipi, fixed("La Jonquera"), "Jonquera, la"),
122
        nom_municipi = str_replace_all(nom_municipi, fixed("L’Hospitalet de Llobregat"), "Hospitalet de Llobregat, l'"),
123
        nom_municipi = str_replace_all(nom_municipi, fixed("El Prat de Llobregat"), "Prat de Llobregat, el"),
124
        nom_municipi = str_replace_all(nom_municipi, fixed("Sant Vicenç del Horts"), "Sant Vicenç dels Horts"),
125
        nom_municipi = str_replace_all(nom_municipi, fixed("Castelló d’Empúries"), "Castelló d'Empúries"),
126
        nom_municipi = str_replace_all(nom_municipi, fixed("Castell-Platja d’Aro"), "Castell d'Aro, Platja d'Aro i s'Agaró"),
127
        nom_municipi = str_replace_all(nom_municipi, fixed("El Vendrell"), "Vendrell, el")
128
      )  %>% 
129
      left_join(
130
        muni_cat %>% select(nom, nom_provincia),
131
        by=c("nom_municipi"="nom")
132
        )
133
    })
134
135
  output$distPlot <- renderPlotly({
136
    # generate bins based on input$bins from ui.R
137
    plot_ly(x = ~ dataset() %>% filter(nom_provincia %in% input$myProvincies) %>% pull(nom_municipi), type = "histogram") %>%
138
      layout(xaxis = list(title = 'Municipi'), 
139
             yaxis = list(title = 'N'))
140
  })
141
  
142
  output$mymap <- renderLeaflet({
143
    leaflet(width="100%", height="100%") %>%
144
145
      # OS map layer
146
      addProviderTiles(providers$Esri.WorldImagery, group="ESRI Satellite",
147
                       options=leafletOptions(maxNativeZoom=19,maxZoom=100)) %>%
148
      addProviderTiles("OpenStreetMap",
149
                       options=leafletOptions(maxNativeZoom=19,maxZoom=100)) %>%
150
151
      # Sample points
152
      # generate radius based on input$myradius from ui.R
153
      addCircleMarkers(data=dataset() %>% filter(nom_provincia %in% input$myProvincies),
154
                       radius=input$myradius, weight=2, color="red") %>%
155
156
      # Add layer control elements
157
      addLayersControl(baseGroups = c("OpenStreetMap", "ESRI Satellite"),
158
                       options = layersControlOptions(collapsed = TRUE,
159
                                                      autoZIndex = F))
160
    
161
162
  })
163
  
164
  output$myTable <- renderDT({
165
    head(dataset() %>% tibble() %>% 
166
           filter(nom_provincia %in% input$myProvincies) %>% 
167
           select(-arxiu_origen,-ordre, -starts_with("municipi"), -cp_num, -geometry),
168
         input$numRows)
169
  },
170
  options = list(dom='ftip',
171
                 lengthMenu = list(c(5, 10, -1), c('5', '10', 'All'))
172
                 )
173
  )
174
  
175
  output$indicator <- renderText(
176
    nrow(dataset() %>% tibble() %>% filter(nom_provincia %in% input$myProvincies))
177
  )
178
}
179
180
shinyApp(ui, server)


1.4. Publicar l'app a shinyapps.io

Pots emprar el teu compte de posit.cloud a https://www.shinyapps.io/
O bé, fer-te un de nou de franc.

I segueix les instruccions que t'hi donaràn allà per tal de publicar la teva app shiny local al seu servidor.

Està explicat també pas a pas en aquest tutorial:
https://statsandr.com/blog/how-to-publish-shiny-app-example-with-shinyapps-io/

Més informació a:
https://shiny.posit.co/r/articles/share/shinyapps/

1.4.1. App Sales-de-joc

16
 
1
> install.packages("rsconnect")
2
The following package(s) will be installed:
3
- packrat   [0.9.2]
4
- PKI       [0.1-12]
5
- rsconnect [1.2.2]
6
These packages will be installed into "~/code/curs-r-avancat-equips/renv/library/R-4.3/x86_64-pc-linux-gnu".
7
8
Do you want to proceed? [Y/n]: Y
9
10
# Installing packages --------------------------------------------------------
11
- Installing PKI ...                            OK [linked from cache]
12
- Installing packrat ...                        OK [linked from cache]
13
- Installing rsconnect ...                      OK [linked from cache]
14
Successfully installed 3 packages in 39 milliseconds.
15
> rsconnect::setAccountInfo(name='myshinyiointernalusername', token='mytokenXXX', secret='mysecretXXX')
16
> library(rsconnect)


Em faltaven els arxius de dades que s'agafaven de carpetes gernanes del projecte de RStudio, fora de la carpeta de l'app shiny. Els he copiat els 2 arxius dins de una nova carpeta filla "dades/", i he tornat a fer "Deploy":

24
 
1
> rsconnect::deployApp('sessio_05/shiny-sales-de-joc')
2
── Preparing for deployment ───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
3
Re-deploying "shiny-sales-de-joc" using "server: shinyapps.io / username: onuka7-xavier-de0pedro0puente"
4
Looking up application with id "11822654"...
5
Found application <https://onuka7-xavier-de0pedro0puente.shinyapps.io/shiny-sales-de-joc/>
6
Bundling 3 files: app.R, dades/muni_cat.csv, and dades/salons_de_joc_en_la_web.xlsx
7
Capturing R dependencies with renv
8
Found 122 dependencies
9
Created 98,363b bundle
10
Uploading bundle...
11
Uploaded bundle with id 8522558
12
── Deploying to server ────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
13
Waiting for task: 1408200276
14
  building: Processing bundle: 8522558
15
  building: Building image: 10366677
16
  building: Installing system dependencies
17
  building: Fetching packages
18
  building: Installing packages
19
  building: Installing files
20
  building: Pushing image: 10366677
21
  deploying: Starting instances
22
  terminating: Stopping old instances
23
── Deployment complete ────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
24
Successfully deployed to <https://onuka7-xavier-de0pedro0puente.shinyapps.io/shiny-sales-de-joc/>


240421 Rstudio Rsconnect Deploy Shinyappsio Sales De Joc 00

URL a la app:
https://onuka7-xavier-de0pedro0puente.shinyapps.io/shiny-sales-de-joc/

240421 Rsconnect Deploy Shinyappsio Sales De Joc 00

1.5. ShinyLive

ShinyLive (per exportar apps shiny per a que funcionin sense requerir servidor, sino tot en navegador):
https://cloud.r-project.org/web/packages/shinylive/index.html

Explicació recent dels autors a Posit (2023-10):
R Shiny without a server: webR and Shinylive by George Stagg at the Shiny in Production 2023 conference.
https://www.youtube.com/watch?v=GlZKReTx8GA

2. Altres: Dash per a R

Dash per a R: Create beautiful, analytic web applications in R.
https://github.com/plotly/dashR

Dash Enterprise App Gallery
https://dash.gallery/Portal/

3. Mostrar progrés projecte

Avançar la feina que hem estat fent del projecte per equips, i mostrar-ho als altres equips.


Noms alias d'aquest pàgina: CursRAvancatEquipsS5

Comments

There are no comments at this time.
Image Llavor: nom \ˈllavor\ : el principi d'alguna cosa que continua desenvolupant-se o creixent

Llavors de coneixement

Canvia l'Idioma