import json
import pandas as pd
df_marf = pd.read_csv("data/food_recipe_marf.csv")
df_marf['상세 레시피'] = [json.loads(_) for _ in df_marf['상세 레시피']]
df_marf.head(3)
레시피 이름 | 레시피 코드 | 상세 레시피 | 음식분류코드 | 음식분류 | 조리시간 | 분량 | 대표이미지 URL | |
---|---|---|---|---|---|---|---|---|
0 | 콩비지동그랑땡 | 195453 | {'계란': '5개', '전분': '1/2T', '부침가루': '1/2T', '소금... | 3010018 | 부침 | 30분 | 3인분 | http://file.okdab.com/recipe/14829957726840013... |
1 | 누드김밥 | 195428 | {'통깨': '약간', '마요네즈': '1T', '설탕': '0.5T', '식초':... | 3010001 | 밥 | 20분 | 3인분 | http://file.okdab.com/recipe/14829933250580012... |
2 | 쪽파 새우강회 | 180363 | {'설탕': '1+1/2T', '통깨': '약간', '식초': '2T', '고추장'... | 3010007 | 나물/생채/샐러드 | 20분 | 2인분 | http://file.okdab.com/recipe/14829900265530011... |
import json
with open("data/food_recipie.json", "r", encoding='utf-8-sig') as f:
recipe_data = f.read()
recipe_json = json.loads(recipe_data)
df_menuzen = pd.DataFrame([(_, recipe_json[_])
for _ in list(recipe_json.keys())],
columns= ['menu', 'recipe'])
df_menuzen.head(3)
menu | recipe | |
---|---|---|
0 | 멕시칸샐러드 | {'스모크햄': 10.0, '양배추': 20.0, '당근': 10.0, '오이': ... |
1 | 호박전 | {'쥬키니': 60.0, '계란': 20.0} |
2 | 양파간장지 | {'양파': 30.0, '청량': 50.0, '얼갈이': 55.0, '양파 ': 4... |
조금 더 표준화된 데이터 찾아서 정리하기 List String -> List Data
import json, ast
import pandas as pd
df_menu_10000 = pd.read_csv("data/food_recipe_10000.csv", sep=";", header=None)
df_menu_10000.columns = ['url', 'menu', 'tags', 'recipes']
df_menu_10000.recipes = [ast.literal_eval(_) for _ in df_menu_10000.recipes]
df_menu_10000 = df_menu_10000.reindex(columns=['url','menu','recipes'])
print(df_menu_10000.shape)
df_menu_10000.head(2)
(71998, 3)
url | menu | recipes | |
---|---|---|---|
0 | /recipe/6923603 | 임성근의 김치콩나물죽, 두부두루치기 알토란 261회 | [[김치콩나물죽 재료], 신김치|1/4포기,콩나물|2줌,바지락살|1+1/2컵,참기름... |
1 | /recipe/6923602 | 또띠아 사과 샌드위치 | [[재료], 또띠아|2장,사과|1개,피자치즈|1컵,양파|1/2개,소시지|약간,시금치... |
from collections import Counter
count_items = dict(Counter([len(_) for _ in df_menu_10000.recipes]))
sorted(count_items.items(), key=lambda x:x[0], reverse = False)
[(2, 34734), (4, 31132), (6, 4865), (8, 1030), (10, 159), (12, 52), (14, 20), (16, 4), (26, 1), (32, 1)]
import json
import pandas as pd
df_safe = pd.read_csv("data/food_recipe_safe.csv")
col_temps = ['메뉴명','조리방법','요리종류','해쉬태그','이미지경로(소)','이미지경로(대)','재료정보']
df_safe = df_safe.loc[:, col_temps]
df_safe.재료정보 = [_.split('\n') for _ in df_safe.재료정보.fillna('')]
df_safe.head(2)
메뉴명 | 조리방법 | 요리종류 | 해쉬태그 | 이미지경로(소) | 이미지경로(대) | 재료정보 | |
---|---|---|---|---|---|---|---|
0 | 칼륨 듬뿍 고구마죽 | 끓이기 | 후식 | NaN | http://www.foodsafetykorea.go.kr/uploadimg/coo... | http://www.foodsafetykorea.go.kr/uploadimg/coo... | [고구마죽, 고구마 100g(2/3개), 설탕 2g(1/3작은술), 찹쌀가루 3g(... |
1 | 누룽지 두부 계란죽 | 끓이기 | 밥 | 순두부 | http://www.foodsafetykorea.go.kr/uploadimg/coo... | http://www.foodsafetykorea.go.kr/uploadimg/coo... | [채소준비, 애호박 30g(1/6개), 표고버섯 20g(2개), 당근 5g(3×2×... |
레시피 데이터 전처리 및 단위기준 일치사전 만들기
계량법 안내
1큰술(1T, 1Ts) = 1숟가락 15ml = 3t (밥숟가락 뜨면 1큰술)
1작은술(1t, 1ts) 5ml (티스푼으로는 2스푼이 1작은술)
1컵(1Cup, 1C) 200ml = 16T (한국,중국,일본) (서양(미국)은 1C가 240~250ml)
1종이컵 180ml; 1oz 28.3g
1파운드(lb) 약 0.453 킬로그램(kg)
1갤런(gallon) 약 3.78 리터(ℓ)
1꼬집 약 2g 정도이며 '약간'이라고 표현하기도 함
조금 약간의 2~3배
적당량 기호에 따라 마음대로 조절해서 넣으란 표현
1줌 한손 가득 (예시 : 멸치 1줌 = 국멸치인 경우 12~15마리, 나물 1줌은 50g) 크게 1줌 = 2줌 [1줌의 두배]
1주먹 여자 어른의 주먹크기, 고기로는 100g
1토막 2~3cm두께 정도의 분량
마늘 1톨 깐 마늘 한쪽
생강 1쪽 마늘 1톨의 크기와 비슷
생강 1톨 아기 손바닥만한 크기의 통생강 1개
고기 1근 600g
채소 1근 400g
채소 1봉지 200g 정도
units = {
"15ml":["1큰술","1T","1Ts","3t"],
"5ml":["1작은술","1t","1ts"],
"200ml":["1컵","1Cup","1C"],
"250ml":["16T", "1C"],
"180ml":["1종이컵"],
"28.3g":["1oz"],
"453g":["1파운드","lb"],
"3780ml":["1갤런","gallon"],
"2g":["1꼬집",'약간'],
"4g":["조금"],
"6g":["조금"],
"10g":["적당량"],
"50g":["1줌"], # 나물
"100g":["1큰줌"], # 나물
"13마리":["1줌"], # 멸치
"26마리":["1큰줌"], # 멸치
"100g":["1주먹"], # 여자 어른의 주먹크기
"3cm":["1토막"],
"1알":["1톨","1쪽"], # 마늘, 생강 등
"600g":["1근"], # 고기
"400g":["1근"], # 채소
"200g":["1봉지"],
}
results = []
for _ in [v for k,v in units.items()]:
results += _
", ".join(sorted(set(results)))
'16T, 1C, 1Cup, 1T, 1Ts, 1oz, 1t, 1ts, 1갤런, 1근, 1꼬집, 1봉지, 1작은술, 1종이컵, 1주먹, 1줌, 1쪽, 1컵, 1큰술, 1큰줌, 1토막, 1톨, 1파운드, 3t, gallon, lb, 약간, 적당량, 조금'
자료가 많고, 기준단위를 만들기에 유용
import json
import pandas as pd
df_safe = pd.read_csv("data/food_recipe_safe.csv")
df_safe = df_safe.loc[:, ['메뉴명','재료정보']]
df_safe.재료정보 = [_.split('\n') for _ in df_safe.재료정보.fillna('')]
df_safe_recipe = df_safe["재료정보"]
df_safe_recipe[:4]
0 [고구마죽, 고구마 100g(2/3개), 설탕 2g(1/3작은술), 찹쌀가루 3g(... 1 [채소준비, 애호박 30g(1/6개), 표고버섯 20g(2개), 당근 5g(3×2×... 2 [초밥, 밥 210g(1공기), 배합초, 식초 20g(1⅓큰술), 설탕 10g(2작... 3 [두부 곤약잡곡밥, 두부 110g(⅓모), 흰쌀 15g, 현미쌀 3g, 찹쌀 3g,... Name: 재료정보, dtype: object
from collections import Counter
count_items = dict(Counter([len(_) for no, _ in enumerate(df_safe_recipe)]))
sorted(count_items.items(), key=lambda x:x[0], reverse = False)
[(1, 459), (2, 127), (3, 202), (4, 190), (5, 95), (6, 76), (7, 24), (8, 14), (9, 9), (10, 1), (12, 1)]
# 단어만 있으면 key, () 가 포함시 Value 로 변환작업 진행하기
temp = "녹두 전(10g/12)"
temp = "맛있는 얼큰 부침개"
import re
if temp.strip().replace(" ","") == "".join(re.findall("[가-힣]+", temp)):
print("제목", temp.strip().replace(" ",""), "".join(re.findall("[가-힣]+", temp)))
else:
print("레시피")
제목 맛있는얼큰부침개 맛있는얼큰부침개
# 중간묶음 전처리
from collections import defaultdict
results, data = [], defaultdict(int)
for no, items in enumerate(df_safe_recipe):
data = defaultdict(int) # 개별 레시피 데이터
for _ in items: # 중간제목 발견시
if _.replace(" ","").strip() == "".join(re.findall("[가-힣]+", _)):
idx_token = _ # 임시 Token 을 메모리에 올리고 data도 추가
data[_]
else:
if idx_token: data[idx_token] = _
else: data['레시피'] = _
results.append([no, data])
len(results), results[997:999]
(1198, [[997, defaultdict(int, {'레시피': '고등어 35g, 전분 5g, 땅콩 1g, 튀김기름 5g [고등어 밑 양념]생강즙 1g, 청주 2g, 소금적당량, 후춧가루 적당량[조림장]간장 1g, 고추장 3g, 토마토케첩 3g, 설탕 1g, 물엿 3g, 물 5g'})], [998, defaultdict(int, {'레시피': '꽃게 70g, 청주 2g, 전분 3g, 실파 5g, 참기름 2g, 건고추 3g, 마늘다진것 3g, 생강다진것 2g, 소금적당량, 후춧가루적당량 [양념장]간장 2g, 청주 2g, 설탕 3g, 물 3g'})]])
# 결과값 내용분석
count_items = dict(Counter([len(_[1]) for _ in results]))
sorted(count_items.items(), key=lambda x:x[0], reverse = False)
[(1, 1017), (2, 98), (3, 60), (4, 21), (5, 2)]
Step1 => Step2 => Step3 단계별 결과값 저장하기
re_key = '\[(.+?)\]'
menus = results[997][1]['레시피']# .replace(']',')').replace('[','(')
# Key 와 Value 값 구분하기
import re
tokens_values = re.split(re_key, menus) # Token 추출
tokens_key = re.findall(re_key, menus) # Key 선별
token_values = [_ for _ in tokens_values if _ not in tokens_key] # Value 선별 (Key 만 제외)
if len(tokens_key) < len(token_values):
if len(tokens_key)+1 == len(token_values):
tokens_key = ['레시피']+tokens_key
data = {tokens_key[no]:_ for no, _ in enumerate(token_values)}
elif len(tokens_key) == len(token_values):
data = {tokens_key[no]:_ for no, _ in enumerate(token_values)}
data
{'레시피': '고등어 35g, 전분 5g, 땅콩 1g, 튀김기름 5g ', '고등어 밑 양념': '생강즙 1g, 청주 2g, 소금적당량, 후춧가루 적당량', '조림장': '간장 1g, 고추장 3g, 토마토케첩 3g, 설탕 1g, 물엿 3g, 물 5g'}
['레시피']+tokens_key, token_values
(['레시피', '고등어 밑 양념', '조림장'], ['고등어 35g, 전분 5g, 땅콩 1g, 튀김기름 5g ', '생강즙 1g, 청주 2g, 소금적당량, 후춧가루 적당량', '간장 1g, 고추장 3g, 토마토케첩 3g, 설탕 1g, 물엿 3g, 물 5g'])
if len(tokens_key) == 1:
tokens_key = tokens_key[0]
tokens_key
# if len(tokens_values)%2 == 1:
# tokens_values = ['레시피'] + tokens_values
tokens_values = re.split('\[\w+\]', menus)
len(tokens_values)
2
for _ in tokens_values:
import re
df_safe.loc[993]["재료정보"]
df_safe["재료정보"][528]
for _ in df_safe_recipe:
[_ for _ in df_safe_recipe if len(_) > 3]
pd.DataFrame(df_safe_recipe).to_csv("recipe_temp.csv", index=None, sep="|", header=None)
df_safe_recipe[410]
# 재료 목록을 우선 모아서 정리하기
계량법 안내
1큰술(1T, 1Ts) = 1숟가락 15ml = 3t (밥숟가락 뜨면 1큰술)
1작은술(1t, 1ts) 5ml (티스푼으로는 2스푼이 1작은술)
1컵(1Cup, 1C) 200ml = 16T (한국,중국,일본) (서양(미국)은 1C가 240~250ml)
1종이컵 180ml; 1oz 28.3g
1파운드(lb) 약 0.453 킬로그램(kg)
1갤런(gallon) 약 3.78 리터(ℓ)
1꼬집 약 2g 정도이며 '약간'이라고 표현하기도 함
조금 약간의 2~3배
적당량 기호에 따라 마음대로 조절해서 넣으란 표현
1줌 한손 가득 (예시 : 멸치 1줌 = 국멸치인 경우 12~15마리, 나물 1줌은 50g) 크게 1줌 = 2줌 [1줌의 두배]
1주먹 여자 어른의 주먹크기, 고기로는 100g
1토막 2~3cm두께 정도의 분량
마늘 1톨 깐 마늘 한쪽
생강 1쪽 마늘 1톨의 크기와 비슷
생강 1톨 아기 손바닥만한 크기의 통생강 1개
고기 1근 600g
채소 1근 400g
채소 1봉지 200g 정도
df_safe["재료정보"]
# Excel 파일 내부 Sheet 목록의 출력
file_name = r'data/momukji_lab_Tag작업.xlsx'
import ast, json, xlrd
import pandas as pd
xls = xlrd.open_workbook(file_name, on_demand=True)
sht_names = [_ for _ in xls.sheet_names()]; print(sht_names)
df_orf = pd.read_excel(file_name, sheet_name=sht_names[1])
df = df_orf[df_orf.구분=='국/탕류']
df = df.reset_index(drop=True)
df.shape, df.tail(3)
['레시피_식약처', '레시피Tag', '작업모음', '영양정보', '제철정보', '식재료가격', '공산품정보', '식단예제']
((361, 5), 구분 메뉴명 대분류 중분류 원메뉴 358 국/탕류 황태국_해장 NaN 해물탕/찌개 NaN 359 국/탕류 후랑크소시지_김치찌개 NaN 김치국/찌개 NaN 360 국/탕류 후랑크소시지_두부찌개 NaN 두부국/찌개 NaN)
작업 진행한 내용과 수집한 데이터 정리하기
df_taged = pd.read_csv('muyong_tags.csv')
df_taged.head(2)
구분 | 메뉴명 | 대분류 | 중분류 | 원메뉴 | |
---|---|---|---|---|---|
0 | 국/찌개 | LA김치두부찌개 | 찌개 | 두부국/찌개 | 두부찌개 |
1 | 국/찌개 | LA두부찌개 | 찌개 | 두부국/찌개 | 두부찌개 |
df_org = df_orf[df_orf["구분"]!='국/탕류']
df_org.head(2)
구분 | 메뉴명 | 대분류 | 중분류 | 원메뉴 | |
---|---|---|---|---|---|
0 | 반찬 | 가지,애호박,오이,부추무침 | NaN | NaN | NaN |
1 | 반찬 | 고사리,무나물,호박볶음 | NaN | NaN | NaN |
pd.concat([df_taged, df_org], axis=0).to_csv("momukji_taged_temp.csv", encoding="cp949")
메뉴명에서 연관된 레시피 찾기 및 연결
# 식약처 레시피 호출
import pandas as pd
df_menu_mfds = pd.read_excel(file_name, sheet_name=sht_names[0])
df_menu_mfds = df_menu_mfds.loc[:,['메뉴명','조리방법','요리종류','해쉬태그','재료정보']]
df_menu_mfds.재료정보 = [_.split('\n') for _ in df_menu_mfds.재료정보.fillna('')]
df_menu_mfds.head(2)
df_menu_10000.recipes[100]
x = ast.literal_eval(df_menu_10000.recipes[0])
x
json.loads(df_menu_10000.recipes[0])
type(df_menu_10000.recipes[0])
# 10,000 개의 레시피에서 세부정보 수집 및 정리
df_menu_10000.recipes = [json.loads(_) for _ in df_menu_10000.recipes]
메뉴명에서 연관된 레시피 찾기 및 연결
# Excel 파일 내부 Sheet 목록의 출력
file_name = r'data/momukji_lab_full.xlsx'
xls = xlrd.open_workbook(file_name, on_demand=True)
sht_names = [_ for _ in xls.sheet_names()]
df_menu_zen = pd.read_excel(file_name, sheet_name=sht_names[-2])
df_menu_zen.tail(3)
# df_menu_zen.iloc[:, 2:]
# Excel 파일 내부 Sheet 목록의 출력
file_name = r'data/momukji_lab_Tag작업.xlsx'
import xlrd
xls = xlrd.open_workbook(file_name, on_demand=True)
sht_names = [_ for _ in xls.sheet_names()]
select_sheet = sht_names[1]
select_sheet, "/".join(sht_names)
df_menu_mfds.iloc[159,:].재료정보
df_menu_mfds.iloc[159,:]
Counter([len(_) for no, _ in enumerate(df_menu_mfds.재료정보)])
[_ for no, _ in enumerate(df_menu_mfds.재료정보) if len(_) == 3][:2]
df_menu_mfds.재료정보[1].split('\n')
# Excel 파일 내부 Sheet 목록의 출력
file_name = r'data/momukji_lab_Tag작업.xlsx'
import xlrd
xls = xlrd.open_workbook(file_name, on_demand=True)
sht_names = [_ for _ in xls.sheet_names()]
select_sheet = sht_names[1]
select_sheet, "/".join(sht_names)
import pandas as pd
df_org = pd.read_excel(file_name, sheet_name=select_sheet)
df = df_org[df_org.구분=='국/탕류']
# df = df.reset_index(drop=True)
df.shape, df.tail(3)
result = []
for _ in df.메뉴명:
if _.find("찌개") != -1:
result.append("찌개")
else: result.append("국")
df.대분류 = result
df.구분 = '국/찌개'
# df.to_csv("muyong_tags.csv", index=None)
df.tail(3)
df_mid_term = sorted(set(df.중분류))
",".join(df_mid_term)
Regex 를 활용하여 전처리 작업 진행 및 Sheet 의 Cell 내용
# 0 번 컬럼의 내용 보완
menu_name = df_mid_term[0]
df.원메뉴[df.중분류 == menu_name] = menu_name
df[df.중분류 == menu_name]
# 1 계란국 편집
menu_name = df_mid_term[1]
df.원메뉴[df.중분류 == menu_name] = menu_name
df.loc[98].원메뉴 = "부추국"
df[df.중분류 == menu_name]
# 2 근대국 편집
menu_name = df_mid_term[2]
df.원메뉴[df.중분류 == menu_name] = menu_name
# df.loc[98].원메뉴 = "부추국"
df[df.중분류 == menu_name]
df.loc[26].대분류
# 3 김치국/찌개
menu_name = df_mid_term[3]
for _ in list(df[df.중분류 == menu_name].index):
if df.loc[_].대분류 == '국':
df.loc[_].원메뉴 = '김칫국'
else:
df.loc[_].원메뉴 = '김치찌개'
df[df.중분류 == menu_name]
df.원메뉴[df.중분류 == menu_name]# = menu_name
# df.loc[98].원메뉴 = "부추국"
df.to_csv("muyong_tags.csv", index=None)
df[df.중분류 == menu_name]
df[df.중분류 == df_mid_term[0]].원메뉴 = '감자탕'
# = df_mid_term[0]
# df.loc[list(df[df.중분류 == df_mid_term[0]].index), :]
df[df.중분류 == df_mid_term[0]]
df = df.loc[:, ["메뉴명","구분","중분류","원메뉴","분류명"]]
import pandas as pd
df = pd.read_csv("muyong_tags.csv")
df.tail(3)
list(set(df.원메뉴))
df[df.원메뉴.isna()].index
len(["찌개" for _ in df.메뉴명 if _.find("찌개") != -1])
df.
import pandas as pd
food_menu_org = pd.read_csv("data/food_recipe.csv")
food_menu_org.shape, food_menu_org.head(1)
from momukji import Nlp
nlp = Nlp('data/nouns_tokens.txt')
menu_valid = [["_".join(nlp.food_nouns(_)), _] for _ in food_menu_org.메뉴명]
food_menu_org.insert(2, 'menu_token',[_[0] for _ in menu_valid])
print(food_menu_org.head(2))
food_menu_org.to_csv("data/food_recipe_addToken.csv", index=None)
빠르고, 정형화된 데이터 중심의 작업진행
# 저장된 내용 확인하기
import pandas as pd
df_menu = pd.read_csv("data/food_recipe_10000.csv", sep=';', header=None)
df_menu.columns = ['url','menu','tags','recipe']
menu_valid = [["_".join(nlp.food_nouns(_)), _] for _ in df_menu.menu]
df_menu.head(1), menu_valid[:5]
import re
df_menu.menu = [re.sub("\d+회", "", _).strip() for _ in df_menu.menu]
df_menu.menu = [re.sub("\d+분", "", _).strip() for _ in df_menu.menu]
",".join(list(df_menu.menu)[:20])
menu_valid = [["_".join(nlp.food_nouns(_)), _] for _ in df_menu.menu.fillna("")]
menu_valid[:5]
"///".join([_[0]+":"+_[1] for _ in menu_valid])