Pizzapp: una aplicación web con Shiny para decidir qué pizza comprar

Con tantas marcas, precios y tamaños, a veces es difícil decidir qué pizza comprar. Esta aplicación para amantes de la pizza (con o sin piña) te ayudará a tomar la mejor decisión mostrándote el precio por centímetro cuadrado de pizza.

La aplicación Pizzapp está desarrollada con R y Shiny. Su procedimiento es simple: permite comparar varias pizzas (hasta 3) conociendo su diámetro y precio. La web calcula el área total de pizza y el precio que cuesta cada centímetro cuadrado de pizza. En general, las pizzas más grandes tienen el \(\text{cm}^2\) más barato, pero esto no siempre es así.

Pizzapp te muestra el tamaño relativo de las pizzas (esto es, la pizza se hace más grande en comparación con las demás pizzas si aumentas su diámetro). Todo gracias a este trocito de código: el diámetro de cada pizza se divide entre el máximo de los diámetros, y ese valor en porcentaje es el ancho con el que se muestra la imagen de la pizza.

...
tags$img(src = "pizza.png",
         width = paste0(100 * input$d1 / max(input$d1, input$d2, input$d3), "%"))
...

Un dato que puede resultar sorprendente: una pizza de 20 centímetros de diámetro equivale (en área) a cuatro pizzas de 10 centímetros de diámetro.

En este gif puedes ver el funcionamiento de Pizzapp:

Pizzapp está disponible en el siguiente enlace:

https://dredondo.shinyapps.io/Pizzapp/

Para acabar, dejo el código de Pizzapp aquí abajo y también en GitHub.

library(dplyr)
library(shiny)
library(shinythemes)
library(shinyWidgets)
library(png)

ui <- fluidPage(theme = shinytheme ("readable"), #themeSelector(),
                titlePanel(tags$h1(tags$b("Pizzapp")), windowTitle = "Pizzapp"),
                setBackgroundImage(src = "fondo.png"),
                tags$h3("Creada por ", tags$a("Daniel Redondo.", href = "http://www.danielredondo.com")),
                tags$h4("Con tantas marcas, precios y tamaños, a veces es difícil decidir qué pizza comprar.
                       Esta aplicación para amantes de la pizza te ayudará a tomar la mejor decisión
                       mostrándote el precio por centímetro cuadrado de pizza."),
                tags$i(tags$b("Disclaimer"), ": El creador de Pizzapp apoya fuertemente la pizza con piña."),
                
                fluidRow(
                  column(8, ""),
                  column(4, checkboxInput("trespizzas", "Comparar 3 pizzas", FALSE, width = '400px'))
                ),
                
                fluidRow(
                  column(4, h2("Pizza 1:"),
                         fluidRow(column(6, numericInput(inputId = "d1", 
                                                         label = "Diámetro en cm:",
                                                         value = "25",
                                                         width = "100%"
                         )),
                         column(6,numericInput(inputId = "p1", 
                                               label = "Precio :",
                                               value = "12"
                         ))),
                         
                         hr(),
                         
                         uiOutput("img1")
                         
                  ),
                  
                  column(4,
                         h2("Pizza 2:"),
                         fluidRow(column(6, numericInput(inputId = "d2", 
                                                         label = "Diámetro en cm:",
                                                         value = "35",
                                                         width = "100%"
                         )),
                         column(6,numericInput(inputId = "p2", 
                                               label = "Precio :",
                                               value = "17"
                         ))),
                         
                         hr(),
                         
                         uiOutput("img2")
                  ),
                  column(4, 
                         conditionalPanel(condition = "input.trespizzas == true", 
                                          h2("Pizza 3:"),
                                          fluidRow(column(6, numericInput(inputId = "d3", 
                                                                          label = "Diámetro en cm:",
                                                                          value = "45",
                                                                          width = "100%"
                                          )),
                                          column(6,numericInput(inputId = "p3", 
                                                                label = "Precio :",
                                                                value = "25"
                                          ))),
                                          
                                          hr(),
                                          
                                          uiOutput("img3")
                                          
                         )
                  )
                  
                )
                
)

server <- function(input, output) {
  
  
  output$img1 <- renderUI(tags$div(tags$img(src="pizza.png", width = paste0(100 * input$d1 / max(input$d1, input$d2, input$d3), "%")),
                                   tags$h3(if(input$d1 > 0 & input$p1 > 0) {
                                     # area
                                     HTML(paste0(round(pi * (input$d1 / 2) ^ 2, 2), " cm", tags$sup(2), "<br><br>",
                                                 # Price/cm2
                                                 round(100 * input$p1 / (pi * (input$d1 / 2) ^ 2), 2), " céntimos/cm", tags$sup(2)))
                                   }, style = "position: absolute; top: 40%; left: 50%; transform: translate(-50%, -50%);"),
                                   style = "position: absolute; text-align:center; color: black; font-weight: bold; text-shadow: -1px 0 white, 0 1px white, 1px 0 white, 0 -1px white;"))
  
  output$img2 <- renderUI(tags$div(tags$img(src="pizza.png", width = paste0(100 * input$d2 / max(input$d1, input$d2, input$d3), "%")),
                                   tags$h3(if(input$d2 > 0 & input$p2 > 0) {
                                     # area
                                     HTML(paste0(round(pi * (input$d2 / 2) ^ 2, 2), " cm", tags$sup(2), "<br><br>",
                                                 # Price/cm2
                                                 round(100 * input$p2 / (pi * (input$d2 / 2) ^ 2), 2), " céntimos/cm", tags$sup(2)))
                                   }, style = "position: absolute; top: 40%; left: 50%; transform: translate(-50%, -50%);"),
                                   style = "position: absolute; text-align:center; color: black; font-weight: bold; text-shadow: -1px 0 white, 0 1px white, 1px 0 white, 0 -1px white;"))
  
  output$img3 <- renderUI(tags$div(tags$img(src="pizza.png", width = paste0(100 * input$d3 / max(input$d1, input$d2, input$d3), "%")),
                                   tags$h3(if(input$d3 > 0 & input$p3 > 0) {
                                     # area
                                     HTML(paste0(round(pi * (input$d3 / 2) ^ 2, 2), " cm", tags$sup(2), "<br><br>",
                                                 # Price/cm2
                                                 round(100 * input$p3 / (pi * (input$d3 / 2) ^ 2), 2), " céntimos/cm", tags$sup(2)))
                                   }, style = "position: absolute; top: 40%; left: 50%; transform: translate(-50%, -50%);"),
                                   style = "position: absolute; text-align:center; color: black; font-weight: bold; text-shadow: -1px 0 white, 0 1px white, 1px 0 white, 0 -1px white;"))
  
}

shinyApp(ui = ui, server = server)
Posted on:
April 26, 2022
Length:
4 minute read, 699 words
See Also: