File size: 5,117 Bytes
1b91aee
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
# Phase 5 β€” Nutrition Integration

## Compliments Reference DB Pipeline

**Version:** 1.0.0
**Date:** 2026-07-30
**Status:** PASS

---

## Purpose

Phase 5 integrates nutrition data from the authoritative source into the Compliments Reference DB. It joins nutrition.parquet with the product pipeline using deterministic matching by external_id.

---

## Inputs

| Dataset | Source | Description |
|---------|--------|-------------|
| `nutrition.parquet` | `saraNour/compliments-brand/source_of_truth/` | Authoritative nutrition data (4,440 Γ— 21) |
| `products.parquet` | `saraNour/compliments-brand/source_of_truth/` | Authoritative product catalog (4,440 Γ— 16) |
| `product_group_mapping.csv` | Phase 3 output | Product β†’ group mapping (4,440 Γ— 14) |
| `product_variant_mapping.parquet` | Phase 4 output | Product β†’ variant mapping (4,440 Γ— 11) |

---

## Outputs

All production data tables are Parquet.

### product_group_mapping.parquet
- Phase 3 mapping converted to Parquet for downstream consumption
- 4,440 rows Γ— 14 columns

### nutrition_cleaned.parquet
- Cleaned/validated nutrition source
- Original values preserved
- Quality flags included
- 4,440 rows Γ— 23 columns

### product_nutrition_mapping.parquet
- Product ↔ nutrition mapping with group_id and variant_id
- 4,440 rows Γ— 27 columns

### nutrition_per_100g.parquet
- Normalized per-100g nutrition values
- Conversion/provenance metadata
- 4,440 rows Γ— 24 columns

### phase5_statistics.parquet
- Summary metrics

### phase5_validation.parquet
- Validation checks and results

---

## Matching Strategy

**Primary key:** `external_id` (exact match)
**Confidence:** HIGH
**Coverage:** 100% (4,440/4,440)

No fallback matching was needed. The relationship is 1:1.

---

## Normalization Strategy

Nutrition values are normalized to per-100g only when a reliable serving-size conversion is possible.

| Method | Count | Description |
|--------|------:|-------------|
| Direct 100g/mL | 150 | serving_size is 100 g or 100 mL |
| Scaled to 100g/mL | 1,351 | Serving size in g or mL, scaled proportionally |
| Not normalized | 2,939 | Ambiguous serving unit or missing serving_size |

### Why Not Normalized?

- **Missing serving_size** (1,505 records): Non-food products (light bulbs, gloves, etc.)
- **Ambiguous serving unit** (1,434 records): tbsp, cup, tsp, slices, pieces, etc. β€” no reliable gram equivalent available
- **No fabrication**: We do NOT invent serving weight conversions

---

## Suspicious Value Policy

Suspicious values are **flagged, not overwritten**.

| Field | Threshold | Records Flagged |
|-------|-----------|----------------:|
| calories | > 1000 | 1 |
| fat_g | > 100 | 1 |
| protein_g | > 100 | 1 |

Original values are preserved in `nutrition_cleaned.parquet` with `nutrition_quality_status = 'SUSPICIOUS'`.

---

## Quality Status

| Status | Count | Description |
|--------|------:|-------------|
| VALID | 2,932 | Normal nutrition values |
| MISSING | 1,505 | All 17 nutrition fields null (non-food products) |
| SUSPICIOUS | 3 | Out-of-range values flagged |

---

## Validation

| Rule | Description | Result |
|------|-------------|--------|
| 1 | All products have nutrition match | PASS |
| 2 | No duplicate external_ids | PASS |
| 3 | No duplicate matches | PASS |
| 4 | Suspicious values preserved | PASS |
| 5 | No fabricated values | PASS |
| 6 | No external data used | PASS |
| 7 | All outputs Parquet | PASS |
| 8 | No LLM used | PASS |
| **Overall** | | **PASS** |

---

## Traceability

```
products.parquet (source of truth)
    ↓
nutrition.parquet (source of truth)
    ↓
Phase 5: nutrition_cleaned.parquet
    ↓
Phase 5: product_nutrition_mapping.parquet
    ↓ (group_id from Phase 3, variant_id from Phase 4)
Phase 5: nutrition_per_100g.parquet
    ↓
Phase 6: Nutrition Scoring
```

---

## Limitations

1. **Per-100g normalization is partial** β€” only possible for ~34% of records (1,501/4,440)
2. **Serving size parsing is limited** β€” complex formats like "1 cup (250 mL)" are not parsed
3. **Suspicious values are flagged, not corrected** β€” requires domain expert review
4. **Non-food products have no nutrition** β€” 1,505 records with all-null nutrition fields

---

## Files

```
phase5/
β”œβ”€β”€ README.md
β”œβ”€β”€ src/
β”‚   └── phase5.py
β”œβ”€β”€ notebooks/
β”‚   β”œβ”€β”€ phase5.ipynb
β”‚   └── phase5_executed.ipynb
β”œβ”€β”€ outputs/
β”‚   β”œβ”€β”€ product_group_mapping.parquet
β”‚   β”œβ”€β”€ nutrition_cleaned.parquet
β”‚   β”œβ”€β”€ product_nutrition_mapping.parquet
β”‚   β”œβ”€β”€ nutrition_per_100g.parquet
β”‚   β”œβ”€β”€ phase5_statistics.parquet
β”‚   └── phase5_validation.parquet
β”œβ”€β”€ validation/
β”‚   └── phase5_validation.json
└── statistics/
    └── phase5_statistics.json
```

---

## How to Run

```bash
cd /home/sara/gsoc/compliments-reference-db
python -m phase5.src.phase5
```

---

## LLM Usage

None. All matching is deterministic by external_id.

## External Datasets

None. Only authoritative nutrition source used.

---

*Generated by Phase 5 Production Pipeline*
*Date: 2026-07-30*