Guía Nutricional con Shiny: Selección de Alimentos de la Tabla Peruana de composición de alimentos (4ta Edición)

Basado en las Tablas Peruanas de composición de Alimentos, Ministerio de Salud del Perú, Lima.
Quarto
ShinnyApp
Autor/a

Sergio Jácobo

Fecha de publicación

15 de abril de 2023

A quien va dirigido?

A todas los profesionales en nutrición que desean planificar o programar sus dietas nutricionales en base a la composición nutricional de diversos alimentos en la cocina peruana según la cantidad deseada.

Implementación

Versión 2 ✅:

  • Se incluyeron alimentos compuestos como platos de entrada y almuerzo.
  • Se incluyó la tabla de anexos de codigos de componentes.
  • Se centró el contenido de las tablas.
  • Se mejoró la salida luego de seleccionar cada tabla principal y se incluyó una opción de copiado.

Versión 1 :

  • Es posible calcular cualquier composición en base a la cantidad ingresada por el usuario en gramos.

  • Solo se incluyeron alimentos individuales y no compuestos.

El Código

Mostrar u ocultar el código
setwd("Ruta/a/tu/proyecto/")

library(shiny)
library(DT) # Manejo de tablas en formato Data Frame
library(shinyjs)

# Cargar datos para alimentos individuales
1alimentos <- read.csv("alimentos.csv")
colnames(alimentos) <- c(
    "COD", "NUM", "ALIMENTO", "ENERCKCAL", "ENERCKJ", "WATER", "PROCNT",
    "FAT", "CHOCDF", "ZN", "K", "P", "FE", "VITA",
    "ACFOLIC", "VITC", "NA"
)
alimentos <- alimentos[, c(
    "COD", "NUM", "ALIMENTO", "ENERCKCAL", "ENERCKJ", "WATER", "PROCNT",
    "FAT", "CHOCDF", "ZN", "K", "P", "FE", "VITA", "ACFOLIC", "VITC", "NA"
)]

# Cargar datos para alimentos compuestos
2platos <- read.csv("alimentosCompuestos.csv")
colnames(platos) <- c(
    "COD", "NUM", "ALIMENTO", "ENERCKCAL", "ENERCKJ", "WATER", "PROCNT",
    "FAT", "CHOCDF", "CHOAVL", "FIBTG", "ASH", "CA", "P", "ZN", "FE", "VITA", "THIA",
    "RIBF", "NIA", "VITC", "ACFOLIC", "NA", "K", "ESTRATO"
)
platos <- platos[, c(
    "COD", "NUM", "ALIMENTO", "ENERCKCAL", "ENERCKJ", "WATER", "PROCNT", "FAT", "CHOCDF",
    "ZN", "K", "P", "FE", "VITA", "ACFOLIC", "VITC", "NA"
)]


# Creamos tablas de Anexo
3codigo <- c("A", "B", "C", "D", "E", "F", "G", "H", "J", "K", "L", "Q", "T", "U", "SE", "SS")
categoria <- c(
    "Cereales y derivados", "Verduras, hortalizas y derivados", "Frutas y derivados",
    "Grasas, aceites y oleaginosas", "Pescados y mariscos", "Carnes y derivados",
    "Leche y derivados", "Bebidas (alcohólicas y analcohólicas)", "Huevos y derivados",
    "Productos azucarados", "Misceláneos", "Alimentos infantiles", "Leguminosas y derivados",
    "Tubérculos, raíces y derivados", "Alimentos preparados (entrada)",
    "Alimentos preparados (segundo)"
)
codigoGrupo <- data.frame(codigo, categoria)
colnames(codigoGrupo) <- c("Código", "Categoría")


# Cargas coódigos de componentes - Anexo
4anexoCodigo <- read.csv("anexosCodigoComponentes.csv")
colnames(anexoCodigo) <- c("Componente", "Identificador INFOODS", "Unidad", "Comentario")

# Definir interfaz
5ui <- fluidPage(
6    includeCSS("styles.css"),
    titlePanel("TABLAS PERUANAS DE COMPOSICIÓN DE ALIMENTOS - 2017"),
    h2(tags$a("Fuente: Centro Nacional de Alimentación y Nutrición, 2017, Ministerio de Salud del Perú, Lima.",
        href = "https://www.gob.pe/institucion/ins/informes-publicaciones/4231115-tablas-peruanas-de-composicion-de-alimentos"
    )),
    h3("Modificado para uso particular en planificación de dietas. Basado en la experiencia de Rosa Zavaleta Gavidia (Nutricionista CNP: 5681)."),
    h3(class = "bold-text", "Nota: Composición en 100 g de alimento"),
7    numericInput("proportion", "Nueva composición (gramos)?", value = 100, min = 1, max = 500),
8    useShinyjs(),
9    tabsetPanel(
        tabPanel(
            "Alimentos individuales",
            dataTableOutput("foodTable1"),
            h4(class = "bold-text", "Componentes seleccionados:"),
            tableOutput("selectedData1"),
            actionButton("copyButton1", "Copiar datos seleccionados")
        ),
        tabPanel(
            "Alimentos en platos",
            dataTableOutput("foodTable2"),
            h4("Componentes seleccionados:"),
            tableOutput("selectedData2"),
            actionButton("copyButton2", "Copiar datos seleccionados")
        ),
        tabPanel(
            "Códigos y grupos",
            tableOutput("codigoGrupos"),
            tableOutput("codigoComponentes")
        )
    ),
    hr(),
10    tags$div(
        class = "footer",
        style = "text-align: center; background-color: #333; color: #fff; padding: 20px;",
        tags$h4("¿Te ha gustado esta App?"),
        tags$p(
            "¡Esta aplicación ha sido desarrollada con ",
            tags$a(
                href = "https://shiny.rstudio.com/",
                style = "color: #ffcc00; font-weight: bold;",
                "R Shiny"
            ),
            "!"
        ),
        tags$p(
            "Si quieres aprender más sobre Shiny y crear tus propias aplicaciones interactivas, ",
            tags$a(
                href = "https://shiny.rstudio.com/tutorial/",
                style = "color: #ffcc00; font-weight: bold;",
                "haz clic aquí"
            ),
            " para acceder al tutorial oficial."
        ),
        tags$p(
            "¡Comienza a explorar el poder de Shiny hoy mismo!",
            style = "font-weight: bold;"
        )
    )
)

# Definir server
server <- function(input, output, session) {
11    getComposition <- function(input_table) {
        proportionConversion <- input$proportion
        idx <- input[[input_table]]
        selectedRow <- alimentos[idx, c("PROCNT", "FAT", "CHOCDF", "ZN", "K", "P", "FE", "VITA", "ACFOLIC", "VITC", "NA")]
        selectedRow <- selectedRow * proportionConversion / 100
        rownames(selectedRow) <- NULL
        selectedRow
    }

12    output$foodTable1 <- renderDataTable(
        alimentos,
        server = FALSE, selection = "single",
        options = list(
            pageLength = 15,
            columnDefs = list(
                list(
                    targets = "_all",
                    className = "dt-center"
                )
            )
        )
    )

13    output$selectedData1 <- renderTable({
        getComposition("foodTable1_rows_selected")
    })

    output$foodTable2 <- renderDataTable(
        platos,
        server = FALSE, selection = "single",
        options = list(
            pageLength = 15,
            columnDefs = list(
                list(
                    targets = "_all",
                    className = "dt-center"
                )
            )
        )
    )

    output$selectedData2 <- renderTable({
        getComposition("foodTable2_rows_selected")
    })

14    output$codigoGrupos <- renderTable(codigoGrupo)

    output$codigoComponentes <- renderTable(anexoCodigo)

15    observeEvent(input$copyButton1, {
        selectedData <- getComposition("foodTable1_rows_selected")
        if (length(input$foodTable1_rows_selected) > 0) {
            clipboard <- apply(selectedData, 2, paste, collapse = " ")
            writeClipboard(clipboard)
            shinyjs::alert("Datos copiados al portapapeles")
        } else {
            shinyjs::alert("Selecciona una fila para copiar los datos")
        }
    })

    observeEvent(input$copyButton2, {
        selectedData <- getComposition("foodTable2_rows_selected")
        if (length(input$foodTable2_rows_selected) > 0) {
            clipboard <- apply(selectedData, 2, paste, collapse = " ")
            writeClipboard(clipboard)
            shinyjs::alert("Datos copiados al portapapeles")
        } else {
            shinyjs::alert("Selecciona una fila para copiar los datos")
        }
    })
}

# Ejecutar la aplicación Shiny
16shinyApp(ui, server)
1
Cargar tabla de alimentos individuales (alimentos.csv), seleccionar datos requeridos y modificar sus atributos (nombre de columnas).
2
Cargar tabla de alimentos compustos (alimentosCompuestos.csv), seleccionar datos requeridos y modificar sus atributos (nombre columnas).
3
Crear tabla de anexos para alimentos según código por grupo nutricional (Opcional).
4
Crear tabla de anexos para alimentos según código de componentes nutricional (Opcional).
5
Implementar la interfaz de usuario de la aplicación Shiny llamando a fluidPage.
6
Incluir ciertos estilos de contenido (archivo css).
7
Definir una entrada de texto para la nueva composición de alimentos deseada.
8
Complemento para mostrar ayudas visuales (mensajes).
9
Mostrar múltiples tablas mediante mediante pestañas separadas con tabPanel().
10
Agregar un pie de nota con detalles de la aplicación.
11
Implementar la función server que define la lógica del programa. Definir la función para manipular la fila seleccionada de las tablas de composición.
12
Renderizar las tablas principales de alimentos. Para centrar todo el contenido de las tablas se creó un estilo css dt-center.
13
Renderizar los datos de componentes de interés (salida).
14
Renderizar las tablas de Anexos.
15
Evento que permite copiar los datos seleccionados al portapapeles. Utilizando el paso 8.
16
Implementar la aplicación llamando a shinyApp.

El demo ⏩

Aplicación de composición de tablas de alimentos usando Shiny

Aplicación Shiny
Más allá de esta guía

Revisar la página oficial para obtener las Tablas de Composición completas

Volver arriba

Reutilización

Cómo citar

BibTeX
@online{jácobo2023,
  author = {Jácobo, Sergio},
  title = {Guía Nutricional con Shiny: Selección de Alimentos de la
    Tabla Peruana de composición de alimentos (4ta Edición)},
  date = {2023-04-15},
  url = {https://sergiojacobo.com/blog/posts/2023/01/01.html},
  langid = {es}
}
Por favor, cita este trabajo como:
Jácobo, Sergio. 2023. “Guía Nutricional con Shiny: Selección de Alimentos de la Tabla Peruana de composición de alimentos (4ta Edición).” April 15, 2023. https://sergiojacobo.com/blog/posts/2023/01/01.html.