{r setup, include=FALSE} knitr::opts_chunk$set(echo = TRUE)
Este documento ejecuta un modelo de programación lineal
(PL) para generar un plan de alimentación personalizado
utilizando el Sistema Mexicano de Alimentos Equivalentes
(SMAE).
El modelo considera requerimientos energéticos, distribución de
macronutrientes y límites por categoría alimentaria.
library(lpSolve)
## Warning: package 'lpSolve' was built under R version 4.3.3
library(readr)
library(tidyverse)
## Warning: package 'tidyr' was built under R version 4.3.3
## ── Attaching core tidyverse packages ──────────────────────── tidyverse 2.0.0 ──
## ✔ dplyr 1.1.2 ✔ purrr 1.0.2
## ✔ forcats 1.0.0 ✔ stringr 1.5.0
## ✔ ggplot2 3.5.2 ✔ tibble 3.2.1
## ✔ lubridate 1.9.2 ✔ tidyr 1.3.1
## ── Conflicts ────────────────────────────────────────── tidyverse_conflicts() ──
## ✖ dplyr::filter() masks stats::filter()
## ✖ dplyr::lag() masks stats::lag()
## ℹ Use the conflicted package (<http://conflicted.r-lib.org/>) to force all conflicts to become errors
library(stringr)
library(dplyr)
# --- Cargar archivos ---
smae <- read_csv("C:/Users/geova/Downloads/smae1.csv")
## Rows: 2871 Columns: 27
## ── Column specification ────────────────────────────────────────────────────────
## Delimiter: ","
## chr (20): Alimento, Categoria, Unidad, AG saturados (g), AG monoinsaturados ...
## dbl (7): Cantidad, Peso bruto, g, Peso neto, g, Energia, Proteinas, Lipidos...
##
## ℹ Use `spec()` to retrieve the full column specification for this data.
## ℹ Specify the column types or set `show_col_types = FALSE` to quiet this message.
smae_reducido <- read_csv("C:/Users/geova/OneDrive/Documentos/curso de titulacion/PROYECTO FINAL/smae_reducido_macronutrientes1.csv")
## Rows: 17 Columns: 5
## ── Column specification ────────────────────────────────────────────────────────
## Delimiter: ","
## chr (1): Grupo
## dbl (4): Energia, Proteina, Lipidos, Carbohidratos
##
## ℹ Use `spec()` to retrieve the full column specification for this data.
## ℹ Specify the column types or set `show_col_types = FALSE` to quiet this message.
df_principal <- smae
df_secundario <- smae_reducido
genero <- 0 # 0 hombre, 1 mujer
edad <- 25
peso <- 85
altura <- 180
ejercicio <- 1 # 0 nada, 1 ligero, 2 moderado, 3 fuerte, 4 muy fuerte
altura_m <- altura/100
IMC <- peso/(altura_m*altura_m)
if(IMC>24.9){
peso <- 24.9*(altura_m*altura_m)
}
if(IMC<18.5){
peso <- 18.5*(altura_m*altura_m)
}
ifelse(genero == 0,
TMB <- 66.4730 + (13.7516*peso) + (5.0033*altura) - (6.7550*edad),
TMB <- 655.0955 + (9.5634*peso) + (1.8449*altura) - (4.6756*edad)
)
## [1] 1907.616
factor_act <- c(1.2, 1.375, 1.55, 1.725, 1.9)
calorias_necesarias <- TMB * factor_act[ejercicio]
calorias_necesarias
## [1] 2289.139
objetivo_calorias <- calorias_necesarias
objetivo_proteinas_min <- (calorias_necesarias * 0.1)/4
objetivo_proteinas_max <- (calorias_necesarias * 0.15)/4
objetivo_carbohidratos_min <- (calorias_necesarias * 0.55)/4
objetivo_carbohidratos_max <- (calorias_necesarias * 0.60)/4
objetivo_grasas_min <- (calorias_necesarias * 0.2)/9
objetivo_grasas_max <- (calorias_necesarias * 0.25)/9
mapa_categorias <- list(
"Verduras" = c("Verduras"),
"Frutas" = c("Frutas"),
"Cereales" = c("Cereales S/G", "Cereales C/G"),
"Leguminosas" = c("Leguminosas"),
"AOA" = c("AOA MBAG", "AOA BAG", "AOA MAG", "AOA AAG"),
"Leche" = c("Leche Entera", "Leche Descremada", "Leche Semidescremada", "Leche con azucar"),
"Grasas" = c("Grasas con proteina", "Grasas sin proteina"),
"Azucares sin grasa"=c("Azucares sin grasa"),
"Azucares con grasa"=c("Azucares con grasa")
)
df_secundario$CategoriaGeneral <- NA
for (cat in names(mapa_categorias)) {
subcats <- mapa_categorias[[cat]]
df_secundario$CategoriaGeneral[df_secundario$Grupo %in% subcats] <- cat
}
df_secundario$costo <- c(rep(1,17))
cal <- df_secundario$Energia
pro <- df_secundario$Proteina
carb <- df_secundario$Carbohidratos
gras <- df_secundario$Lipidos
costo <- df_secundario$costo
limites_categorias <- data.frame(
Categoria = names(mapa_categorias),
Min = c(2, 1, 2, 1, 2, 1, 1, 1, 1), #Verduras,Frutas,Cereales,Leguminosas,AOA,Leche,
Max = c(5, 5, 5, 7, 5, 2, 5, 5, 5) #Grasas,AzúcaresS/G,AzúcaresC/G
)
matriz_cat <- list()
dir_cat <- c()
rhs_cat <- c()
for (i in seq_len(nrow(limites_categorias))) {
cat <- limites_categorias$Categoria[i]
fila <- as.numeric(df_secundario$CategoriaGeneral == cat)
if (!is.na(limites_categorias$Min[i]) && limites_categorias$Min[i] > 0) {
matriz_cat <- append(matriz_cat, list(fila))
dir_cat <- c(dir_cat, ">=")
rhs_cat <- c(rhs_cat, limites_categorias$Min[i])
}
if (!is.na(limites_categorias$Max[i]) && limites_categorias$Max[i] > 0) {
matriz_cat <- append(matriz_cat, list(fila))
dir_cat <- c(dir_cat, "<=")
rhs_cat <- c(rhs_cat, limites_categorias$Max[i])
}
}
matriz_cat <- do.call(rbind, matriz_cat)
matriz <- rbind(
cal, # min calorías
cal, #max calorias
pro, # min proteínas
pro, #max proteinas
carb, # min carbohidrato
carb, #max carbohidratos
gras, # min grasas
gras, #max carbohidratos
matriz_cat
)
direcciones <- c(
"<=", # min calorías
">=", # max calorias
">=", # min proteínas
"<=", # max proteinas
">=", # min carbohidratos
"<=", # max carbohidratos
">=", # min grasas
"<=", #max grasas
dir_cat
)
rhs <- c(
1.05*objetivo_calorias,
0.95*objetivo_calorias,
objetivo_proteinas_min,
objetivo_proteinas_max,
objetivo_carbohidratos_min,
objetivo_carbohidratos_max,
objetivo_grasas_min,
objetivo_grasas_max,
rhs_cat
)
resultado <- lp(
direction = "min",
objective.in = costo,
const.mat = matriz,
const.dir = direcciones,
const.rhs = rhs,
all.int = TRUE
)
if (resultado$status == 0) {
cat("Solución óptima encontrada:\n\n")
solucion <- resultado$solution
seleccion <- data.frame(
CategoriaGeneral = df_secundario$CategoriaGeneral,
Porciones = solucion,
Calorias = cal * solucion,
Proteinas = pro * solucion,
Carbohidratos = carb * solucion,
Grasas = gras * solucion
) %>% filter(Porciones > 0)
print(seleccion)
cat("\n--- TOTALES NUTRICIONALES ---\n")
cat(sprintf("Calorías: %.2f (Objetivo: %.2f)\n",
sum(cal * solucion), objetivo_calorias))
cat(sprintf("Proteínas: %.2fg (Objetivo: %.2fg - %.2fg)\n",
sum(pro * solucion), objetivo_proteinas_min, objetivo_proteinas_max))
cat(sprintf("Carbohidratos: %.2fg (Objetivo: %.2fg - %.2fg)\n",
sum(carb * solucion), objetivo_carbohidratos_min, objetivo_carbohidratos_max))
cat(sprintf("Grasas: %.2fg (Objetivo: %.2fg - %.2fg)\n",
sum(gras * solucion), objetivo_grasas_min, objetivo_grasas_max))
} else {
cat("No se encontró una solución óptima.\n")
}
## Solución óptima encontrada:
##
## CategoriaGeneral Porciones Calorias Proteinas Carbohidratos Grasas
## 1 Verduras 2 50 4 8 0
## 2 Frutas 4 240 0 60 0
## 3 Cereales 5 575 10 75 25
## 4 Leguminosas 5 600 40 100 5
## 5 AOA 1 75 7 0 5
## 6 AOA 1 100 7 0 8
## 7 Leche 2 400 16 60 10
## 8 Grasas 1 45 0 0 5
## 9 Azucares sin grasa 1 40 0 10 0
## 10 Azucares con grasa 1 85 0 10 5
##
## --- TOTALES NUTRICIONALES ---
## Calorías: 2210.00 (Objetivo: 2289.14)
## Proteínas: 84.00g (Objetivo: 57.23g - 85.84g)
## Carbohidratos: 323.00g (Objetivo: 314.76g - 343.37g)
## Grasas: 63.00g (Objetivo: 50.87g - 63.59g)