Несколько месяцев назад я увидел в Твиттере ссылку на удивительный график, на котором изображены сходства различных продуктов на основе их вкусовых соединений, а также их распространенность в рецептах (см. Целое исследование, Сеть вкусов и Принципы сочетания продуктов ). , Я подумал, что это действительно здорово и заинтересовался потенциальным использованием данных для чего-то немного другого; чтобы выяснить, какие ингредиенты имеют тенденцию коррелировать по рецептам. Я написал по электронной почте одному из авторов, Йонг-Йол Ану, который, кстати, настоящий менш, и он сообщил мне, что необработанные рецептурные данные легко доступны на его сайте!
Учитывая мою цель поиска того, какие ингредиенты коррелируют между рецептами, я подумал, что это была бы идеальная возможность использовать тематическое моделирование (здесь я использую скрытое выделение дирихле или LDA). Обычно в тематическом моделировании у вас много работы по фильтрации. Не так с этими данными рецепта, где все слова (ингредиенты), включенные в корпус, представляют потенциальный интерес, и нет даже знаков препинания! Темы, выходящие из анализа, будут представлять группы ингредиентов, которые встречаются друг с другом в разных рецептах, и, возможно, научат меня кое-чему о кулинарии (о которой я знаю очень мало!).
Весь мой код находится внизу, поэтому здесь вы найдете только графики и мое текстовое резюме. Первое, что я сделал, это собрал 3 необработанных файла рецептов, используя python. Каждый файл состоял из одного рецепта в строке, кухня рецепта была первой записью в строке, а все остальные записи (ингредиенты) были разделены символами табуляции. В своем скрипте Python я отделил кухню от ингредиентов и создал два файла, один для рецептов, а другой для кухонь из рецептов.
Затем я загрузил рецепты в R и получил количество слов / ингредиентов. Как вы можете видеть ниже, 3 самых популярных ингредиента — яйцо, пшеница и масло. Это имеет смысл, учитывая тот факт, что примерно 70% всех рецептов относятся к «американской» кухне. Я сделал этот анализ ради новизны, и поэтому я решил, что вытащу эти ингредиенты из состава, прежде чем я продолжу. Яйцо делает меня пукающим, пшеница — это не то, что у меня есть дома в сыром виде, и масло не важно для меня для целей этого анализа!
Вот лучшие ингредиенты без трех отфильтрованных:
Наконец, я запустил LDA, выделив 50 тем и топ-5 наиболее характерных ингредиентов каждой темы. Вы можете увидеть полный набор тем внизу моего поста, но я подумала, что рассмотрю некоторые, которые я нахожу интригующими. Вы, конечно, найдете другие темы интригующими, или некоторые, которые будут странными и неуместными (не стесняйтесь говорить мне в разделе комментариев). Во-первых, тема 4:
[1] "tomato" "garlic" "oregano" "onion" "basil"
Вот группа ингредиентов, которая кажется совершенно итальянской. Ингредиенты, кажется, имеют смысл вместе, и поэтому я думаю, что попробую их вместе в следующий раз, когда я делаю макароны (хотя я не люблю помидоры в их первоначальном виде, только томатный соус).
Далее тема 19:
[1] "vanilla" "cream" "almond" "coconut" "oat"
Это привлекло мое внимание, и мне любопытно, могут ли ингредиенты иметь смысл вместе. Ваниль и сливки имеют смысл … Кажется, добавление кокоса также имеет смысл. Миндаль дал бы этому дополнительный кризис (если это не миндальное молоко!). Однако я не знаю, будет ли это вкусно, поэтому я, наверное, пройду мимо этого.
Далее тема 20:
[1] "onion" "black_pepper" "vegetable_oil" "bell_pepper" "garlic"
Это выглядит вкусно! Я люблю острую пищу, поэтому мне нравится смешивать черный перец с луком, чесноком и сладким перцем!
Далее тема 23:
[1] "vegetable_oil" "soy_sauce" "sesame_oil" "fish" "chicken"
Теперь мы в мясной зоне! Я все за то, чтобы положить соусы / масла на мясо, но совмещать растительное масло, соевый соус и кунжутное масло кажется излишним. Интересно, будет ли соевый соус появляться с растительным маслом или кунжутным маслом отдельно в рецептах, а не связывать их все вместе в одних и тех же рецептах? Мне всегда нравился дополнительный соленый вкус соевого соуса, хотя я знаю, что это ужасно для вас, так как в нем есть глютамат натрия. Интересно, как бы было на вкус растительное масло, соевый соус и курица? Что-то попробовать, наверняка!
Теперь тема 26:
[1] "cumin" "coriander" "turmeric" "fenugreek" "lemongrass"
Это много специй, которые я никогда не использую в своей еде. Не из-за отсутствия желания, а скорее из-за невежества и лени. Одна из моих коллег недавно прокомментировала, что тмин добавляет действительно хороший вкус к еде (я думаю, она назвала это «ближневосточной»). Я никогда не слышал ничего о других специях здесь, но почему бы не попробовать их!
Далее тема 28:
[1] "onion" "vinegar" "garlic" "lemon_juice" "ginger"
Я склонен находить, что что-нибудь с интенсивным ароматом может быть очень аппетитным для меня. Специи, уксус и все, что лимонное — это то, что действительно записывается на моем языке. Таким образом, эта тема выглядит очень интересной для меня, вероятно, в качестве начинки или соуса. Интересно, что здесь появляется имбирь, так как он нейтрализует другие ароматы, поэтому мне интересно, включу ли я его в любой соус, который я делаю?
Последний! Тема 41:
[1] "vanilla" "cocoa" "milk" "cinnamon" "walnut"
Они выглядят как ингредиенты для какого-то хорошего напитка (ты бы раздавил грецкие орехи? Я не уверен!)
Что ж, надеюсь, вам понравилось так же, как и мне! Это не идеальный анализ, но он определенно очень вкусный. 
import os
rfiles = os.listdir('.')
rc = []
for f in rfiles:
if '.txt' in f:
# The recipes come in 3 txt files consisting of 1 recipe per line, the
# cuisine of the recipe as the first entry in the line, and all subsequent ingredient
# entries separated by a tab
infile = open(f, 'r')
rc.append(infile.read())
infile.close()
all_rs = '\n'.join(rc)
import re
line_pat = re.compile('[A-Za-z]+\t.+\n')
recipe_lines = line_pat.findall(all_rs)
new_recipe_lines = []
cuisine_lines = []
for n,r in enumerate(recipe_lines):
# First we find the cuisine of the recipe
cuisine = r[:r.find('\t')]
# Then we append the ingredients withou the cuisine
new_recipe_lines.append(recipe_lines[n].replace(cuisine, ''))
# I saved the cuisines to a different list in case I want to do some
# cuisine analysis later
cuisine_lines.append(cuisine + '\n')
outfile1 = open('recipes combined.tsv', 'wb')
outfile1.write(''.join(new_recipe_lines))
outfile1.close()
outfile2 = open('cuisines.csv', 'wb')
outfile2.write(''.join(cuisine_lines))
outfile2.close()
recipes = readLines('recipes combined.tsv')
# Once I read it into R, I have to get rid of the /t
# characters so that it's more acceptable to the tm package
recipes.new = apply(as.matrix(recipes), 1, function (x) gsub('\t',' ', x))
recipes.corpus = Corpus(VectorSource(recipes.new))
recipes.dtm = DocumentTermMatrix(recipes.corpus)
# Now I filter out any terms that have shown up in less than 10 documents
recipes.dict = Dictionary(findFreqTerms(recipes.dtm,10))
recipes.dtm.filtered = DocumentTermMatrix(recipes.corpus, list(dictionary = recipes.dict))
# Here I get a count of number of ingredients in each document
# with the intent of deleting any documents with 0 ingredients
ingredient.counts = apply(recipes.dtm.filtered, 1, function (x) sum(x))
recipes.dtm.filtered = recipes.dtm.filtered[ingredient.counts > 0]
# Here i get some simple ingredient frequencies so that I can plot them and decide
# which I'd like to filter out
recipes.m = as.matrix(recipes.dtm.filtered)
popularity.of.ingredients = sort(colSums(recipes.m), decreasing=TRUE)
popularity.of.ingredients = data.frame(ingredients = names(popularity.of.ingredients), num_recipes=popularity.of.ingredients)
popularity.of.ingredients$ingredients = reorder(popularity.of.ingredients$ingredients, popularity.of.ingredients$num_recipes)
library(ggplot2)
ggplot(popularity.of.ingredients[1:30,], aes(x=ingredients, y=num_recipes)) + geom_point(size=5, colour="red") + coord_flip() +
ggtitle("Recipe Popularity of Top 30 Ingredients") +
theme(axis.text.x=element_text(size=13,face="bold", colour="black"), axis.text.y=element_text(size=13,colour="black",
face="bold"), axis.title.x=element_text(size=14, face="bold"), axis.title.y=element_text(size=14,face="bold"),
plot.title=element_text(size=24,face="bold"))
# Having found wheat, egg, and butter to be the three most frequent ingredients
# (and not caring too much about them as ingredients in general) I remove them
# from the corpus and redo the document term matrix
recipes.corpus = tm_map(recipes.corpus, removeWords, c("wheat","egg","butter")) # Go back to line 6
recipes.dtm.final = DocumentTermMatrix(recipes.corpus, list(dictionary = recipes.dict))
# Finally, I run the LDA and extract the 5 most
# characteristic ingredients in each topic... yummy!
recipes.lda = LDA(recipes.dtm.filtered, 50)
t = terms(recipes.lda,5)
Topic 1 Topic 2 Topic 3 Topic 4 Topic 5 Topic 6 Topic 7 Topic 8 Topic 9
[1,] "onion" "pepper" "milk" "tomato" "olive_oil" "milk" "milk" "tomato" "garlic"
[2,] "rice" "vinegar" "vanilla" "garlic" "garlic" "nutmeg" "pepper" "cayenne" "cream"
[3,] "cayenne" "onion" "cocoa" "oregano" "onion" "vanilla" "yeast" "olive_oil" "vegetable_oil"
[4,] "chicken_broth" "tomato" "onion" "onion" "black_pepper" "cinnamon" "potato" "garlic" "pepper"
[5,] "olive_oil" "milk" "cane_molasses" "basil" "vinegar" "cream" "lemon_juice" "pepper" "milk"
Topic 10 Topic 11 Topic 12 Topic 13 Topic 14 Topic 15 Topic 16 Topic 17
[1,] "milk" "soy_sauce" "vegetable_oil" "onion" "milk" "tamarind" "milk" "vegetable_oil"
[2,] "cream" "scallion" "milk" "black_pepper" "cinnamon" "onion" "vanilla" "pepper"
[3,] "vanilla" "sesame_oil" "pepper" "vinegar" "onion" "garlic" "cream" "cream"
[4,] "cane_molasses" "cane_molasses" "cane_molasses" "bell_pepper" "cayenne" "corn" "vegetable_oil" "black_pepper"
[5,] "cinnamon" "roasted_sesame_seed" "cinnamon" "bacon" "olive_oil" "vinegar" "garlic" "mustard"
Topic 18 Topic 19 Topic 20 Topic 21 Topic 22 Topic 23 Topic 24 Topic 25 Topic 26
[1,] "cane_molasses" "vanilla" "onion" "garlic" "onion" "vegetable_oil" "onion" "cream" "cumin"
[2,] "onion" "cream" "black_pepper" "cane_molasses" "garlic" "soy_sauce" "garlic" "tomato" "coriander"
[3,] "vinegar" "almond" "vegetable_oil" "vinegar" "tomato" "sesame_oil" "cane_molasses" "chicken" "turmeric"
[4,] "olive_oil" "coconut" "bell_pepper" "black_pepper" "olive_oil" "fish" "tomato" "lemon_juice" "fenugreek"
[5,] "pepper" "oat" "garlic" "soy_sauce" "basil" "chicken" "vegetable_oil" "black_pepper" "lemongrass"
Topic 27 Topic 28 Topic 29 Topic 30 Topic 31 Topic 32 Topic 33 Topic 34 Topic 35
[1,] "onion" "onion" "onion" "onion" "vanilla" "garlic" "onion" "onion" "garlic"
[2,] "garlic" "vinegar" "celery" "pepper" "milk" "onion" "pepper" "garlic" "basil"
[3,] "black_pepper" "garlic" "chicken" "garlic" "garlic" "vegetable_oil" "garlic" "vegetable_oil" "pepper"
[4,] "tomato" "lemon_juice" "vegetable_oil" "parsley" "cinnamon" "cayenne" "black_pepper" "black_pepper" "tomato"
[5,] "olive_oil" "ginger" "carrot" "olive_oil" "cream" "beef" "beef" "chicken" "olive_oil"
Topic 36 Topic 37 Topic 38 Topic 39 Topic 40 Topic 41 Topic 42 Topic 43 Topic 44
[1,] "onion" "onion" "onion" "cayenne" "garlic" "vanilla" "vanilla" "scallion" "milk"
[2,] "garlic" "garlic" "cream" "garlic" "onion" "cocoa" "cane_molasses" "garlic" "tomato"
[3,] "cayenne" "black_pepper" "tomato" "ginger" "bell_pepper" "milk" "cocoa" "ginger" "garlic"
[4,] "vegetable_oil" "lemon_juice" "cane_molasses" "rice" "olive_oil" "cinnamon" "oat" "soybean" "vegetable_oil"
[5,] "oregano" "scallion" "milk" "onion" "milk" "walnut" "milk" "pepper" "cream"
Topic 45 Topic 46 Topic 47 Topic 48 Topic 49 Topic 50
[1,] "onion" "cream" "pepper" "cream" "milk" "olive_oil"
[2,] "cream" "black_pepper" "vegetable_oil" "tomato" "vanilla" "tomato"
[3,] "black_pepper" "chicken_broth" "garlic" "beef" "lard" "parmesan_cheese"
[4,] "milk" "vegetable_oil" "onion" "garlic" "cocoa" "lemon_juice"
[5,] "cinnamon" "garlic" "olive_oil" "carrot" "cane_molasses" "garlic"

