tropicbirdのブログ

データサイエンス分野への転身を目論む三十路(専門は環境分野)。2019年9月からイギリスの予定。

【学習記録】Python データサイエンスハンドブック(40)

オライリーの「Pythonデータサイエンスハンドブック」の学習記録

3.11.3 事例:レシピデータ

・レシピデータは以下からダウンロードする。!curlではなぜか読み込めないのでサイトで直接ダウンロードした。
https://github.com/sameergarg/scala-elasticsearch/raw/master/conf/recipeitems-latest.json.gz
・!gunzipは可能。

In [23]: !gunzip recipeitems-latest.json.gz

#Trainling dataとは「後続のデータ」があること。ファイル全体としてJSONとして完全でないことが原因。
In [24]: try:
    ...:     recipes=pd.read_json('recipeitems-latest.json')
    ...: except ValueError as e:
    ...:     print('ValueError:',e)
    ...:
ValueError: Trailing data

#各行は有効なJSONであることを確認。
In [25]: with open('recipeitems-latest.json')as f:
    ...:     line=f.readline()
    ...: pd.read_json(line).shape
Out[25]: (2, 12)

#工夫してJSONとして読み込めるようにする。(←未理解)
In [26]: with open('recipeitems-latest.json', 'r') as f:
    ...:     data=(line.strip() for line in f)
    ...:     data_json='[{0}]'.format(','.join(data))
    ...: recipes=pd.read_json(data_json)

In [27]: recipes.shape
Out[27]: (173278, 17)

#1行目のデータを確認する。
In [31]: recipes.iloc[0]
Out[31]:
_id                                {'$oid': '5160756b96cc62079cc2db15'}
cookTime                                                          PT30M
creator                                                             NaN
dateModified                                                        NaN
datePublished                                                2013-03-11
description           Late Saturday afternoon, after Marlboro Man ha...
image                 http://static.thepioneerwoman.com/cooking/file...
ingredients           Biscuits\n3 cups All-purpose Flour\n2 Tablespo...
name                                    Drop Biscuits and Sausage Gravy
prepTime                                                          PT10M
recipeCategory                                                      NaN
recipeInstructions                                                  NaN
recipeYield                                                          12
source                                                  thepioneerwoman
totalTime                                                           NaN
ts                                             {'$date': 1365276011104}
url                   http://thepioneerwoman.com/cooking/2013/03/dro...
Name: 0, dtype: object

#材料(ingredients)のデータの特徴(長さ)を確認する。
In [33]: recipes.ingredients.str.len().describe()
Out[33]:
count    173278.000000
mean        244.617926
std         146.705285
min           0.000000
25%         147.000000
50%         221.000000
75%         314.000000
max        9067.000000
Name: ingredients, dtype: float64

#ingredientsが最も長い文字列のnameを確認する。
In [34]: recipes.name[np.argmax(recipes.ingredients.str.len())]
Out[34]: 'Carrot Pineapple Spice & Brownie Layer Cake with Whipped Cream & Cream Cheese Frosting and Marzipan Carrots'

#朝食(breakfastかBreakfast)を含むデータ数を確認する。
In [35]: recipes.description.str.contains('[Bb]reakfast').sum()
Out[35]: 3524

#材料にシナモン(Cinnamonかcinnamon)を含むデータ数を確認する。
In [36]: recipes.ingredients.str.contains('[Cc]innamon').sum()
Out[36]: 10526

#材料にスペルミスのシナモン(Cinamonかcinamon)を含むデータ数を確認する。
In [37]: recipes.ingredients.str.contains('[Cc]inamon').sum()
Out[37]: 11
3.11.3.1 単純なレシピ推奨システム

・材料のリストを与えるとそれら全ての材料を使用するレシピを見つけてくれるシステムを作りたい。
・しかし、材料の行から正規化された材料のリストを抽出することは非常に複雑
・簡単なシステムでは、材料のリストを作り、それぞれのレシピの材料リストにそれらが入っているかだけを調べる。

In [38]: spice_list=['salt','pepper','oregano','sage','parsley',
    ...: 'rosemary','tarragon','thyme','paprika','cumin']

#spice_listの材料が入っているかをbool値を持つDataFrameを作成する。
In [39]: import re
In [40]: spice_df=pd.DataFrame(
    ...: dict((spice, recipes.ingredients.str.contains(spice, re.IGNORECASE))
    ...: for spice in spice_list))

In [41]: spice_df.head()
Out[41]:
    salt  pepper  oregano   sage  parsley  rosemary  tarragon  thyme  paprika  \
0  False   False    False   True    False     False     False  False    False
1  False   False    False  False    False     False     False  False    False
2   True    True    False  False    False     False     False  False    False
3  False   False    False  False    False     False     False  False    False
4  False   False    False  False    False     False     False  False    False

   cumin
0  False
1  False
2   True
3  False
4  False

#上記のDataFrameと後述するqueryメソッドを使えば、特定の材料を含む行を抽出することができる。
In [42]: selection=spice_df.query('parsley & paprika & tarragon')

#10個あることが分かる。
In [43]: len(selection)
Out[43]: 10

In [44]: recipes.name[selection.index]
Out[44]:
2069      All cremat with a Little Gem, dandelion and wa...
74964                         Lobster with Thermidor butter
93768      Burton's Southern Fried Chicken with White Gravy
113926                     Mijo's Slow Cooker Shredded Beef
137686                     Asparagus Soup with Poached Eggs
140530                                 Fried Oyster Po’boys
158475                Lamb shank tagine with herb tabbouleh
158486                 Southern fried chicken in buttermilk
163175            Fried Chicken Sliders with Pickles + Slaw
165243                        Bar Tartine Cauliflower Salad
Name: name, dtype: object