VitaScore GFM
El Gap Filling Module VitaScore calcula los impactos en la salud humana de los productos alimentarios basándose en factores de riesgo dietético del estudio Global Burden of Disease (GBD). Convierte la composición de alimentos en Años de Vida Ajustados por Discapacidad (AVAD), permitiendo comparaciones de impacto en salud junto con métricas ambientales.
Referencia Rápida
| Propiedad | Descripción |
|---|---|
| Se ejecuta en | FoodProductFlowNode |
| Dependencias | AggregationGapFillingWorker, DailyFoodUnitGapFillingWorker |
| Entrada clave | Cantidades de categorías de alimentos, valores nutricionales, unidad de alimento diario |
| Salida | VitaScore en AVAD por factor de riesgo dietético |
| Activador | El producto tiene categorías de alimentos agregadas y unidad de alimento diario |
Cuándo se Ejecuta
El módulo se activa cuando:
- La agregación de categorías de alimentos está completa
- El cálculo de Unidad de Alimento Diario (UAD) está completo
- El nodo tiene datos válidos de
amount_per_category_in_flow - El nodo tiene un valor válido de
daily_food_unit
Salida Clave
El módulo produce:
- VitaScore Total: Impacto agregado en salud en AVAD
- Puntuaciones por factor: Contribuciones individuales de AVAD de cada factor de riesgo dietético
- Versiones actual y heredada: Dos métodos de cálculo para comparación
Metodología Científica
VitaScore cuantifica el impacto en salud del consumo de alimentos usando Años de Vida Ajustados por Discapacidad (AVAD) basados en el estudio Global Burden of Disease. Un AVAD representa la pérdida de un año de salud plena.
Marco del Global Burden of Disease
El estudio GBD identifica factores de riesgo dietético que contribuyen a la carga de enfermedad. El VitaScore usa 13 factores de riesgo agrupados en dos categorías:
Factores de Riesgo Positivos (mayor consumo es beneficioso):
- Dieta baja en frutas
- Dieta baja en verduras
- Dieta baja en cereales integrales
- Dieta baja en frutos secos y semillas
- Dieta baja en leche
Factores de Riesgo Negativos (mayor consumo es perjudicial):
- Dieta alta en sodio
- Dieta alta en carne procesada
- Dieta alta en carne roja
- Dieta alta en energía
- Dieta alta en grasa
- Dieta baja en grasa
- Dieta alta en proteína
- Dieta baja en proteína
Nivel de Exposición de Mínimo Riesgo Teórico (TMREL)
Cada factor de riesgo dietético tiene un rango de consumo óptimo llamado TMREL - el nivel de exposición que minimiza el riesgo para la salud. El VitaScore calcula cuánto se desvía el consumo real de este rango óptimo.
El TMREL se define por dos límites:
- t_1: Límite inferior del rango óptimo
- t_2: Límite superior del rango óptimo
La Fórmula del VitaScore
La fórmula central calcula una fracción de riesgo (f_r) para cada factor de riesgo dietético, luego multiplica por la carga de AVAD asociada:
Para factores positivos (donde consumir más es mejor):
f_r = (t_2 / (t_2 - t_1)) - x_r / (scaling * (t_2 - t_1))
Para factores negativos (donde consumir menos es mejor):
f_r = x_r / (scaling * (t_2 - t_1)) - (t_1 / (t_2 - t_1))
Donde:
- x_r: Cantidad del factor de riesgo en el producto alimentario
- t_1, t_2: Límites inferior y superior del TMREL
- scaling: Factor de normalización (ver abajo)
- f_r: Fracción de riesgo (limitada al rango 0-1)
Cálculo final:
VitaScore[r] = AVAD_r * f_r
VitaScore Total = suma(VitaScore[r] para todos los factores de riesgo)
Métodos de Normalización
El VitaScore soporta tres métodos de normalización para diferentes factores de riesgo:
| Método | Descripción | Uso |
|---|---|---|
| per_dfu | Escalar por Unidad de Alimento Diario | La mayoría de factores de riesgo (frutas, verduras, carne, etc.) |
| per_total_energy | Escalar por contenido energético total | Grasa y proteína como porcentaje de calorías |
| per_self | Sin escalado (factor = 1,0) | Mediciones directas |
Unidad de Alimento Diario (UAD)
La Unidad de Alimento Diario representa la cantidad de consumo diario típica de una categoría de alimentos. Normaliza el cálculo de modo que el impacto en salud de un alimento sea proporcional a cuánto representa de la dieta diaria.
Detalles de Implementación
Factores de Riesgo Dietético Cubiertos
El módulo calcula impactos en salud para 13 factores de riesgo dietético. Cada factor tiene un Nivel de Exposición de Mínimo Riesgo Teórico (TMREL) que define el rango de consumo óptimo.
Factores de Riesgo Positivos (Mayor Consumo es Beneficioso)
| Factor de Riesgo | TMREL Inferior | TMREL Superior | Unidad | Normalización | AVAD | Referencia de Guía Dietética |
|---|---|---|---|---|---|---|
| Dieta baja en frutas | 200 | 300 | g/día | per_dfu | 61,24 | La OMS recomienda ≥400 g/día de frutas y verduras combinadas1 |
| Dieta baja en verduras | 340 | 500 | g/día | per_dfu | 30,57 | La OMS recomienda ≥400 g/día de frutas y verduras combinadas1 |
| Dieta baja en cereales integrales | 100 | 150 | g/día | per_dfu | 82,86 | Guías de EE.UU.: 3-4 porciones/día (~48-64 g)2 |
| Dieta baja en frutos secos y semillas | 16 | 25 | g/día | per_dfu | 13,98 | EAT-Lancet: ~50 g/día de frutos secos3 |
| Dieta baja en leche | 350 | 520 | g/día | per_dfu | 9,42 | 2-3 porciones de lácteos/día (~400-600 ml)4 |
Factores de Riesgo Negativos (Mayor Consumo es Perjudicial)
| Factor de Riesgo | TMREL Inferior | TMREL Superior | Unidad | Normalización | AVAD | Referencia de Guía Dietética |
|---|---|---|---|---|---|---|
| Dieta alta en sodio (sal) | 1 | 5 | g/día | per_dfu | 29,43 | La OMS recomienda <5 g de sal/día (<2 g de sodio)5 |
| Dieta alta en carne procesada | 0 | 4 | g/día | per_dfu | 96,94 | EAT-Lancet: evitar o minimizar carne procesada3 |
| Dieta alta en carne roja | 18 | 27 | g/día | per_dfu | 74,25 | EAT-Lancet: ~14 g/día (~100 g/semana)3 |
Factores de Riesgo de Macronutrientes (Energía y Porcentaje de Energía Total)
| Factor de Riesgo | TMREL Inferior | TMREL Superior | Unidad | Normalización | AVAD | Referencia de Guía Dietética |
|---|---|---|---|---|---|---|
| Dieta alta en energía | 650 | 1250 | kcal | per_self | 88,66 | Una comida equilibrada: 450-850 kcal (~⅓ de 2200 kcal/día)4 |
| Dieta alta en grasa | 27,5% | 50% | % de kcal | per_total_energy | 88,66 | Guías EFSA/EE.UU.: 20-35% de energía de grasa46 |
| Dieta baja en grasa | 5% | 27,5% | % de kcal | per_total_energy | 88,66 | Guías EFSA/EE.UU.: 20-35% de energía de grasa46 |
| Dieta alta en proteína | 22,5% | 60% | % de kcal | per_total_energy | 88,66 | AMDR de EE.UU.: 10-35% de energía de proteína6 |
| Dieta baja en proteína | 0% | 22,5% | % de kcal | per_total_energy | 88,66 | AMDR de EE.UU.: 10-35% de energía de proteína6 |
Los valores de AVAD se expresan como AVAD por 100.000 personas-año y representan la carga de enfermedad atribuible a cada factor de riesgo dietético.
Conversión de Sodio a Sal
Dado que las guías dietéticas a menudo se refieren a sal (cloruro de sodio) en lugar de sodio, el módulo convierte los valores de sodio:
# El sodio es aproximadamente el 39,3% de la sal por masa
NA_PERCENT_IN_NACL = 39.337 # %
# Convertir sodio a equivalente de sal
salt_quantity = sodium_quantity * (100 / NA_PERCENT_IN_NACL)
Conversión de Energía de Macronutrientes
La grasa y proteína se convierten de masa a energía para cálculos de porcentaje de calorías:
FAT_CALORIES_PER_GRAM = 9.0 # kcal/g
PROTEIN_CALORIES_PER_GRAM = 4.0 # kcal/g
fat_kcal = fat_grams * FAT_CALORIES_PER_GRAM
protein_kcal = protein_grams * PROTEIN_CALORIES_PER_GRAM
Soporte de Versiones
El módulo mantiene dos versiones de cálculo:
| Versión | Descripción |
|---|---|
| current | Valores AVAD más recientes del GBD 2021 |
| legacy | Valores AVAD originales para compatibilidad hacia atrás |
Ambas versiones se calculan y almacenan, permitiendo comparación de resultados entre actualizaciones metodológicas.
Referencia Completa del Código
Flujo de Cálculo Principal
async def run(self, calc_graph: CalcGraph) -> None:
"""Realizar cálculo de vitascore."""
# Obtener categorías de alimentos agregadas y unidad de alimento diario
amount_per_category_in_flow_prop = self.node.amount_per_category_in_flow
dfu_prop = self.node.daily_food_unit
# Añadir sal y factores de riesgo derivados de nutrición
salt_qty, energy_qty, fat_qty, protein_qty = (
self.retrieve_salt_and_nutrition_amounts_for_activity_production_amount()
)
# Calcular vitascore para ambas versiones
for version in (VitascoreVersionEnum.legacy, VitascoreVersionEnum.current):
vitascore_for_local = self.compute_vitascore(
amount_per_category_in_flow_prop,
dfu_prop,
version,
ReferenceAmountEnum.amount_for_activity_production_amount,
)
# ... almacenar resultados
Implementación de la Fórmula Central del VitaScore
def vitascore_formula(
self,
food_category: QuantityPackageProp,
dfu: float,
legacy_or_current: str,
for_reference_amount: ReferenceAmountEnum,
) -> dict[UuidStr, ReferencelessQuantityProp]:
"""Fórmula para calcular vitascore."""
vitascore = {
self.gfm_factory.vitascore_term.uid: ReferencelessQuantityProp(
value=0.0, unit_term_uid=self.gfm_factory.daly_unit_term.uid
)
}
for idx, term in enumerate(
self.gfm_factory.positive_terms + self.gfm_factory.negative_terms
):
if term.xid in self.gfm_factory.used_categories_xid:
# Obtener límites TMREL de los datos del término
t_1 = float(term.data.get("tmrel").get("lower"))
t_2 = float(term.data.get("tmrel").get("upper"))
normalization = TmrelNormalizationEnum(
term.data.get("tmrel").get("tmrel_normalization")
)
# Obtener cantidad de categorías de alimentos
if term.uid in amount_per_category_in_flow_present:
x_r = float(amount_per_category_in_flow_present[term.uid].value)
else:
x_r = 0.0
# Obtener carga AVAD para este factor de riesgo
daly_r = float(term.data.get(legacy_or_current).get("amount"))
# Determinar factor de escalado
if normalization == TmrelNormalizationEnum.per_dfu:
scaling = dfu
elif normalization == TmrelNormalizationEnum.per_total_energy:
scaling = energy_kcal_value
elif normalization == TmrelNormalizationEnum.per_self:
scaling = 1.0
# Calcular fracción de riesgo
if scaling <= 0.0:
f_r = 0.0
else:
if idx < len(self.gfm_factory.positive_terms):
# Factores positivos: más es mejor
f_r = (t_2 / (t_2 - t_1)) - x_r / (scaling * (t_2 - t_1))
else:
# Factores negativos: menos es mejor
f_r = x_r / (scaling * (t_2 - t_1)) - (t_1 / (t_2 - t_1))
# Limitar fracción de riesgo a [0, 1]
f_r = max(0, min(1, f_r))
# Calcular y acumular vitascore
vitascore[term.uid] = ReferencelessQuantityProp(
value=daly_r * f_r,
unit_term_uid=self.gfm_factory.daly_unit_term.uid
)
vitascore[self.gfm_factory.vitascore_term.uid].value += daly_r * f_r
return vitascore
Recuperación de Sal y Nutrición
def retrieve_salt_and_nutrition_amounts_for_activity_production_amount(
self,
) -> Tuple[Optional[ReferencelessQuantityProp], ...]:
"""Extraer cantidades de sal y macronutrientes de los datos nutricionales."""
# Comprobar primero nutrientes agregados, luego valores de nutrientes
if aggregated_nutrients := self.node.aggregated_nutrients:
nutrition_pkg = aggregated_nutrients.amount_for_activity_production_amount()
elif nutrient_values := self.node.nutrient_values:
nutrition_pkg = nutrient_values.amount_for_activity_production_amount()
# Manejar división de cloruro de sodio
if nutrition_pkg and (sodium_chloride_term.uid in nutrition_pkg.quantities):
nutrition_pkg = split_sodium_chloride(nutrition_pkg)
# Convertir sodio a sal
if sodium_term.uid in nutrition_pkg.quantities:
salt_qty = nutrition_pkg.quantities[sodium_term.uid].duplicate()
salt_qty.value *= 100 / NA_PERCENT_IN_NACL
# Obtener energía y convertir grasa/proteína a kcal
energy_kcal_qty = nutrition_pkg.quantities.get(energy_term.uid)
if fat_mass_qty := nutrition_pkg.quantities.get(fat_term.uid):
fat_in_grams = convert_to_grams(fat_mass_qty)
fat_qty = ReferencelessQuantityProp(
value=fat_in_grams * FAT_CALORIES_PER_GRAM,
unit_term_uid=kcal_term.uid
)
if protein_mass_qty := nutrition_pkg.quantities.get(protein_term.uid):
protein_in_grams = convert_to_grams(protein_mass_qty)
protein_qty = ReferencelessQuantityProp(
value=protein_in_grams * PROTEIN_CALORIES_PER_GRAM,
unit_term_uid=kcal_term.uid
)
return salt_qty, energy_kcal_qty, fat_qty, protein_qty
Ejemplo de Cálculo
Escenario: Calcular VitaScore para 100g de jamón procesado
Paso 1: Identificar Cantidades de Factores de Riesgo
De la agregación de categorías de alimentos:
- Carne procesada: 100g
- Carne roja: 0g (contada separadamente de procesada)
- Frutas: 0g
- Verduras: 0g
De los valores nutricionales:
- Sodio: 1200mg (se convierte a 3050mg de sal)
- Energía: 145 kcal
- Grasa: 8g (72 kcal)
- Proteína: 18g (72 kcal)
Paso 2: Calcular Fracciones de Riesgo
Dieta alta en carne procesada (factor negativo):
- TMREL: 0-0g por día (lo óptimo es cero consumo)
- Escalado: Unidad de Alimento Diario (asumiendo 2000g de ingesta diaria de alimentos)
- Cantidad normalizada: 100g / 2000g = 0,05 (5% de la ingesta diaria)
- Fracción de riesgo: Calculada según desviación del TMREL
Dieta alta en sodio:
- TMREL: 1000-5000mg por día
- Cantidad de sal: 3050mg
- Fracción de riesgo: Basada en dónde cae 3050mg en el rango TMREL
Dieta baja en frutas (factor positivo):
- Cantidad: 0g
- Fracción de riesgo: Máxima (sin contenido de fruta)
Paso 3: Aplicar Valores AVAD
Cada fracción de riesgo se multiplica por la carga AVAD asociada de los datos GBD:
- Carga AVAD de carne procesada: ~40 AVAD por 100.000 personas-año
- Carga AVAD de sodio: ~30 AVAD por 100.000 personas-año
Paso 4: Sumar VitaScore Total
VitaScore Total = suma de (AVAD_r * f_r) para los 13 factores de riesgo
El resultado se expresa en micro-AVAD por porción, representando la carga proporcional en salud.
Fuentes de Datos
Estudio Global Burden of Disease
El VitaScore se basa en el estudio GBD 2021:
GBD 2021 Risk Factors Collaborators (2024). Global burden and strength of evidence for 88 risk factors in 204 countries and 811 subnational locations, 1990-2021: a systematic analysis for the Global Burden of Disease Study 2021. The Lancet.
Datos clave extraídos:
- Cargas AVAD para cada factor de riesgo dietético
- Rangos TMREL para consumo óptimo
- Estimaciones de riesgo relativo
Valores TMREL
Los Niveles de Exposición de Mínimo Riesgo Teórico provienen de:
- Apéndice 1 del GBD 2021: Especificaciones detalladas de TMREL para cada factor de riesgo
- Materiales Suplementarios de Lancet: Datos de apoyo para la derivación del TMREL
Factores de Mediación
El GBD usa factores de mediación para tener en cuenta vías de riesgo superpuestas. Por ejemplo, la carne roja impacta la salud tanto directamente como a través de su efecto sobre el índice de masa corporal (IMC).
Limitaciones Conocidas
Restricciones Metodológicas
- Promedios poblacionales: Los valores AVAD representan promedios globales o regionales, no riesgo individual
- Especificidad por edad/género: La implementación actual usa valores para toda la población (valores específicos por edad/género disponibles pero no implementados)
- Superposición de factores de riesgo: Los factores de mediación abordan parcialmente pero no completamente los riesgos correlacionados
Limitaciones de Datos
- Coincidencia de alimentos: Requiere clasificación precisa de categorías de alimentos
- Completitud nutricional: Los cálculos de sodio/grasa/proteína dependen de datos nutricionales completos
- Incertidumbre del TMREL: Los rangos de consumo óptimo tienen incertidumbre científica inherente
Lagunas de Cobertura
- Especificidad por país: Los valores AVAD pueden hacerse específicos por país pero actualmente usan estimaciones globales
- Alimentos procesados: Los alimentos procesados complejos pueden tener mapeo de categorías incompleto
- Alimentos novedosos: Las nuevas categorías de alimentos pueden carecer de asociaciones establecidas de factores de riesgo
Referencias
-
GBD 2021 Risk Factors Collaborators (2024). Global burden and strength of evidence for 88 risk factors in 204 countries and 811 subnational locations, 1990-2021. The Lancet, 403(10440), 2162-2203.
-
Eaternity (2017). VitaScore Documentation. https://eaternity.org/assets/smart-chefs/2017-12-12_VitaScore_Documentation_web.pdf
-
Ernstoff, A., et al. (2020). Towards Win-Win Policies for Healthy and Sustainable Diets. Nutrients, 12(9), 2745.
-
Murray, C.J.L., et al. (2020). Global burden of 87 risk factors in 204 countries and territories, 1990-2019: a systematic analysis for the Global Burden of Disease Study 2019. The Lancet, 396(10258), 1223-1249.
-
GBD Results Tool. Institute for Health Metrics and Evaluation. https://vizhub.healthdata.org/