Recipe/Ingredient taxonomy/Ingredient linking
Ingredient linking describes how the links between an ingredient in the ingredients taxonomy is linked to an entry in a food composition database.
Property format
In the ingredients taxonomy and entry (ingredient) consists of a list of ingredients names per language (and possible synonyms) as they are found on packaging. In addition to this language list a list of properties follow. These properties help in linking to other databases (like wikidata, wikipedia), whether the ingredient is vegan, etc.
In order to link to a food composition database a specific format is chosen. The general format for the property is:
<databases-identifier>_<fieldname>:<language>:
The database identifier describes the food composition database that is referenced:
- ciqual_food for the french Ciqual database;
- ifct for the Indian Food Composition tables;
- usda - for the usa database;
The fieldname describes which kind of content is to be expected:
- code - an unique identification code of the ingredient that is used in the food composition database;
- name - a more readable name of the ingredient of the ingredient in the food composition database;
The field language gives the two letter ISO language that is used for the fieldname (only the name). Used are:
- en - for english;
- fr - for french;
Examples
An example:
ciqual_food_code:en: 16128 ciqual_food_name:en: Frying oil ciqual_food_name:fr: Huile pour friture, sans précision
These three properties describe the link to the Ciqual database for the ingredient frying oil (en:frying-oil in the taxonomy). The code in the database is 16123, the english name frying oil and the french name Huile pour friture, sans précision. The french name is a bit more descriptive than the english name in the it states that the entry is for any frying oil, without an oil type specification.
Another example:
usda_ndb_code:en: 4589 usda_ndb_name:en: Fish oil, cod liver
These two properties describe the ingredient 4589 in the USDA Legacy food database. It is a specific variant for fish oil, i.e. cod liver fish oil. There is only an english name associated with this entry.
OFF-database matching
Ingredients found in nutritional databases (NDB) are not always easy to match to the ingredients in the OFF-ingredients taxonomy. The ingredients taxonomy should only contain words (ingredients) found on product ingredient lists. Matching implies that the words used in the taxonomy and NDB need to be compared. There is no formal definition for each ingredient. In order to match OFF-ingredients with NDB-ingredients a set of standard rules has been defined, depending on the situation.
Exact matches
The easiest situation is when there is an exact match between OFF ingredient and NDB ingredient. The words used for the ingredient are then exactly the same. Examples are the en:cod liver fish oil and en:frying oil mentioned above. There can be no doubt what is meant by the words used.
Missing NDB-ingredients
Some ingredients in the taxonomy do not have any match with any database. This might be due to a geographical bias of the database for instance. The ingredient might however resemble an other NDB-ingredient in terms of nutritional values. This can be used as a proxy ingredient.
For instance en:green pepper has not yet a matching NBD match. These are the berries of Piper nigrum, but not yet dried. In this case black pepper might be a (bad - due to different humidity levels) proxy. This can be encoded in the ingredients taxonomy as:
usda_ndb_proxy_code:en: 2030 usda_ndb_proxy_name:en: Spices, pepper, black
Default matches
In many cases the OFF ingredient is underspecified with respect to a NDB-ingredient. NDB-ingredients often have additional adjective raw, uncooked, unprocessed, fresh etc. This extra adjective is not often mentioned on ingredients lists. It is assumed that all ingredients in the ingredients taxonomy underwent minimal processing before they were used in a recipe. This will be used as the default matching.
Thus for instance the ingredient en:sorghum is assumed to be the same as Sorghum, whole, raw in the USDA NDB, i.e. nothing has been done to the grains. This can be encoded as:
ciqual_food_code:en: 9360 ciqual_food_name:en: Sorghum, whole, raw ciqual_food_name:fr: Sorgho entier, cru
Although unprocessed ingredients seem to be the best default, it also depends what is mostly used in a recipe. Thus another ingredient might be a better default [example needed].
Underspecified ingredients
An OFF-ingredient can be underspecified. The OFF-ingredient en:tamarind is named in Ciqual as raw tamarind pulp from immature fruit. As no alternate entry is available, we assume this is actually what is mean on ingredient lists.
Processed ingredients
In the ingredients taxonomy the choice has been made to suppress processed ingredients and only list the ingredient itself. This is done in order to reduce the number of entries. So there are no entries for diced tomatoes, diced cucumber, diced carrots, etc in all languages.
During parsing of the ingredient lists the processes of the processed ingredients are extracted based on the ingredients processing taxonomy.
Some entries in a NDB might list the processed variant of an ingredient. For instance en:turmeric can only be found as ground turmeric or powdered turmeric. To express this it is possible to add an extra line to the ingredient taxonomy entry, like:
ifct_food_code:en: G033 ifct_food_name:en: Turmeric powder ifct_food_process:en: en:ground
Any processing that the parser picks up can thus be matched to the NBD as well. In the en:tamarind case this might be superfluous and does not add much extra.
Alternate processed ingredients
Some ingredients can be associated with multiple processes: for instance en:parsley has an entry fresh and dried in the USDA-database. As fresh comes closes to the original ingredient it can be set as default. As it is undesirable to create a specific entry for en:dried parsley, it can be added as associated entry to the taxonomy entry. This can be encoded in the taxonomy as:
usda_ndb_code:en: 11297 usda_ndb_name:en: Parsley, fresh usda_ndb_process:en: en:fresh usda_ndb_2_code:en: 2029 usda_ndb_2_name:en: Spices, parsley, dried usda_ndb_2_process:en: en:dried
The recipe estimator can use this to iterate through the alternatives to find out which usda entry gives the best results.
Other examples are:
- Ciqual
- Rutabaga: raw, cooked
- Salsify: raw, cooked;
- USDA
- daikon radish: raw and dried;
- sweet potato: raw and frozen;
- spirulina: dried and cooked;
Genuine alternate ingredients
Finally there might be genuine different variants of the same ingredient. These are ones that are determined by any specific process. For instance the USDA NDB has entries for en:Medjool dates and for en:Deglet noor dates, but no generic entry for dates like in Ciqual. By trying these alternate variants the recipe estimator can determine which one fits bests to a date entry in an ingredient list.
Other examples:
- radish: black radish, red radish, daikon, white icicle radish
TODO: how can the recipe estimator know that there are alternatives. We could name the default one a proxy?
Inherited ingredients
If an ingredient has no link to nutritional database, there might be a substitute. If the ingredient has a (nutritional) parent, then the nutritional information of the parent can be used. Or its parent, etc.
Orphaned ingredients
The orphaned ingredients are those in the taxonomy for which there is no link to an entry in any nutritional database.
Statistics
Some statistics of the ingredients taxonomy linking (situation 20 july 2026).
Basic stats
Hierarchy structure
- 4,772 total nodes (4,763 raw
en:entries + 9 synthetic E-number/"additives" nodes created by the script) - 221 root categories
- 3,506 leaf nodes / 1,266 nodes with children
- 595 nodes with more than one parent (multi-parent)
- Max depth: 7 levels
- Depth distribution: 221 roots → 1,019 (d1) → 1,591 (d2) → 1,324 (d3) → 449 (d4) → 103 (d5) → 15 (d6) → 1 (d7)
Largest root categories by total descendant
- vegetable — 549
- fruit — 546
- dairy — 317
- cereal — 230
- oil and fat — 206
- flavouring — 189
- fish — 188
- plant — 181
- added sugar — 154
- animal — 121
Ciqual stats
How well can we map the ingredients in the taxonomy to the various nutritional databases?
| Category | Count | % | Definition |
|---|---|---|---|
| Exact match | 820 | 17.2% | Node itself carries a ciqual_food_code
|
| Proxy match | 159 | 3.3% | Node itself carries a ciqual_proxy_food_code (no exact code)
|
| Multiple ciquals | 0 | 0.0% | Node carries two different Ciqual code numbers |
| Alternate match | 167 | 3.5% | No own code, but ≥1 direct child has an exact/proxy match |
| Inherited match | 1,869 | 39.2% | No own/child match, but an ancestor up the tree has one |
| No match | 1,757 | 6.8% | No code anywhere in the node's own entry, children, or ancestors |
IFCT
| Category | Count | % | Definition |
|---|---|---|---|
| Exact match | 64 | 1.34% | Node itself carries an ifct_food_code
|
| Proxy match | 1 | 0.02% | Node itself carries an ifct_proxy_food_code (no exact)
|
| Multiple ciquals | 0 | 0.0% | Node carries two different IFCT code values |
| Alternate match | 36 | 0.75% | No own code, but ≥1 direct child has an exact/proxy match |
| Inherited match | 248 | 5.20% | No own/child match, but an ancestor up the tree has one |
| No match | 4,423 | 92.69% | No code anywhere in the node's own entry, children, or ancestors |
USDA
| Category | Count | % | Definition |
|---|---|---|---|
| Exact match | 587 | 12.30% | Node itself carries a usda_ndb_code
|
| Proxy match | 236 | 4.95% | Node itself carries a usda_ndb_proxy_code (no exact)
|
| Multiple ciquals | 2 | 0.04% | Node carries two different USDA codes |
| Alternate match | 152 | 3.19% | No own code, but ≥1 direct child has an exact/proxy match |
| Inherited match | 786 | 16.47% | No own/child match, but an ancestor up the tree has one |
| No match | 3,009 | 63.06% | No code anywhere in the node's own entry, children, or ancestors |