Несколько месяцев назад я увидел в Твиттере ссылку на удивительный график, на котором изображены сходства различных продуктов на основе их вкусовых соединений, а также их распространенность в рецептах (см. Целое исследование, Сеть вкусов и Принципы сочетания продуктов ). , Я подумал, что это действительно здорово и заинтересовался потенциальным использованием данных для чего-то немного другого; чтобы выяснить, какие ингредиенты имеют тенденцию коррелировать по рецептам. Я написал по электронной почте одному из авторов, Йонг-Йол Ану, который, кстати, настоящий менш, и он сообщил мне, что необработанные рецептурные данные легко доступны на его сайте!
Учитывая мою цель поиска того, какие ингредиенты коррелируют между рецептами, я подумал, что это была бы идеальная возможность использовать тематическое моделирование (здесь я использую скрытое выделение дирихле или 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"