<SYSTEM_TASK:>
Given the following text description, write Python code to implement the functionality described below step by step
<END_TASK>
<USER_TASK:>
Description:
 Using chef in jupyter notebook
To run chef in the notebook, use the Chef class from ddf_utils.chef.api
Step1:  quickly add lots of similar procedures
Step2:  Error handling
Step3:  Advance usage
<ASSISTANT_TASK:>
Python Code:
import os
import sys
import ruamel.yaml as yaml
from ddf_utils.chef.api import Chef
# at the beginning, initial the chef
chef = Chef()
# adding configs and metadata(to the info section)
(chef.add_config(ddf_dir=os.path.expanduser('~/src/work/Gapminder/datasets'))
     .add_metadata(id='test_dataset', 
                   base=['ddf--transpint--corrupton']))
# adding ingredient, parameters are just like in recipe
i = '''
id: cpi-datapoints
dataset: ddf--transpint--corrupton
key: country, year
value: "*"
'''
d = yaml.round_trip_load(i)
chef.add_ingredient(**d)
# add an other ingredient
chef.add_ingredient(id='bp-datapoints', dataset='ddf--bp--energy', key='geo, year', value='*')
# add procedures, parameters are same as in recipe
chef.add_procedure(collection='datapoints',   # which part of cooking section the procedure is in
                   procedure='translate_header', 
                   ingredients=['bp-datapoints'], 
                   result='bp-datapoints-translate', 
                   options={'dictionary': {'geo': 'country'}})
# add an other procedure
chef.add_procedure(collection='datapoints', 
                   procedure='merge', 
                   ingredients=['bp-datapoints-translate', 'cpi-datapoints'], 
                   result='res')
# you can print the recipe in yaml format
a = chef.to_recipe()
# also in graph
chef.to_graph()
# to run the recipe and get the output:
res = chef.run()
res
res[0].get_data().keys()
res[0].get_data()['biofuels_production_kboed'].sample(5)
res[0].get_data()['cpi'].sample(5)
# we can also create a Chef instance from existing recipes
recipe_file = '../tests/recipes_pass/test_flatten.yml'
print(open(os.path.abspath(recipe_file)).read())
chef = Chef.from_recipe(os.path.expandvars(recipe_file),
                        ddf_dir=os.path.expanduser('/Users/semio/src/work/Gapminder/libs/ddf_utils/tests/datasets'))
chef.to_recipe()
res = chef.run()
res[0].get_data().keys()
res[0].get_data()['agriculture_percentage_f']
Explanation: Using chef in jupyter notebook
To run chef in the notebook, use the Chef class from ddf_utils.chef.api
End of explanation
from ddf_utils.chef.helpers import gen_sym
chef = Chef()
chef.add_config(ddf_dir=os.path.expanduser('~/src/work/Gapminder/datasets'))
chef.add_ingredient(id='population_by_age_dps', 
                    dataset='ddf--unpop--wpp_population_semio',
                    key='country_code,year,age',
                    value=['population'])
collection = 'datapoints'
groups = [list(map(str, range(0, 5))),
          list(map(str, range(5, 10))),
          list(map(str, range(10, 20)))
         ]
names = ['population_0_4', 'population_5_9', 'population_10_19']
ingredients_0 = ['population_by_age_dps']
to_merge = []
for g, n in zip(groups, names):
    
    procedure = 'filter_row'
    options = {
        'filters': {
            'population': {
                'age': g}}}
    result = gen_sym('filter_row', ingredients_0, options)
        
    chef.add_procedure(collection=collection,
                       procedure=procedure,
                       ingredients=ingredients_0,
                       options=options,
                       result=result
                      )
    
    ingredients = [result]
    procedure = 'groupby'
    options = {
        'groupby': ['country_code', 'year'],
        'aggregate': {'population': 'sum'}
    }
    result = gen_sym(procedure, ingredients, options)
    
    chef.add_procedure(collection=collection,
                       procedure=procedure,
                       ingredients=ingredients,
                       options=options,
                       result=result
                      )
    
    ingredients = [result]
    procedure = 'translate_header'
    options = {
        'dictionary': {
            'population': n
        }
    }
    result = gen_sym(procedure, ingredients, options)
    chef.add_procedure(collection=collection,
                   procedure=procedure,
                   ingredients=ingredients,
                   options=options,
                   result=result
                  )
    to_merge.append(result)
chef.add_procedure(collection=collection,
                   procedure='merge',
                   ingredients=to_merge,
                   result='result'
                  )
chef.to_recipe()
chef.to_graph()
res = chef.run()
res
res[0].get_data().keys()
Explanation: quickly add lots of similar procedures
End of explanation
chef = Chef()
i = '''
id: cpi-datapoints
dataset: ddf--transpint--corrupton
key: country, year
value: "*"
snieot: 'soneot'
'''
d = yaml.round_trip_load(i)
chef.add_ingredient(**d)
i = '''
id: cpi-datapoints_
dataset: ddf--transpint--corrupton
oh_my_interesting_key: country, year   # error
value: "*"
'''
d = yaml.round_trip_load(i)
try:
    chef.add_ingredient(**d)
except KeyError as e:
    print(str(e))
i = '''
procedure: my_new_procedure
ingredients:
    - testing
options:
    opt: val
result: result
'''
d = yaml.round_trip_load(i)
chef.add_procedure('datapoints', **d)
Explanation: Error handling
End of explanation
from ddf_utils.chef.ingredient import Ingredient, ProcedureResult
def multiply_1000(chef, ingredients, result, **options):
    ingredients = [chef.dag.get_node(x) for x in ingredients]
    ingredient = ingredients[0].evaluate()
    
    new_data = dict()
    for k, df in ingredient.get_data().items():
        df_ = df.copy()
        df_[k] = df_[k] * 1000
        new_data[k] = df_
        
    return ProcedureResult(chef, result, ingredient.key, new_data)
chef = Chef()
chef.add_config(ddf_dir=os.path.expanduser('~/src/work/Gapminder/datasets'))
i = '''
id: cpi-datapoints
dataset: ddf--transpint--corrupton
key: country, year
value: "*"
'''
d = yaml.round_trip_load(i)
chef.add_ingredient(**d)
chef.register_procedure(multiply_1000)
chef.add_procedure(collection='datapoints',
                   procedure='multiply_1000',
                   result='res',
                   ingredients=['cpi-datapoints']
                  )
res = chef.run()
res[0].get_data()['cpi'].head(5)
chef.ingredients
chef.ingredients[0].get_data()['cpi'].head()  # the original
chef.to_graph()
Explanation: Advance usage: create new procedure
will add description later
End of explanation
<END_TASK>