<SYSTEM_TASK:>
Given the following text description, write Python code to implement the functionality described below step by step
<END_TASK>
<USER_TASK:>
Description:
 Advanced Data Enrichment using CARTO's Data Observatory
This notebook shows how to use CARTOframes to enrich the area of influence of different POIs with data from CARTO's Data Observatory. Please, visit CARTOframes Guides to learn more about the enrichment functionality.
We will show CARTOframes enrichment functionality with an example in which we will quantify the number of eating places within a 5-minute isochrone for all sports POI's in Madrid downtown.
The notebook is organized as follows
Step1:  Set CARTO default credentials
In order to be able to use the Data Observatory via CARTOframes, you need to set your CARTO account credentials first.
Please, visit the Authentication guide for further detail.
Step3:  Note about credentials
For security reasons, we recommend storing your credentials in an external file to prevent publishing them by accident when sharing your notebooks. You can get more information in the section Setting your credentials of the Authentication guide.
<a id='section1'></a>
1. Download sports POIs
We need to start with the initial DataFrame that we would like to enrich. Normally, this initial DataFrame contains your own data that you later enrich with data from the Data Observatory. In this case, we will download all sports POI's and use it as our initial DataFrame.
We first check that we are subscribed to PB POIs dataset in Spain and download the sports POI's within a bounding box covering Madrid downtown. You can calculate your bounding box of interest using bboxfinder.
For a step by step description on how to discover and download premium datasets, take a look at templates
Step4:  <a id='section2'></a>
2. Calculate isochrones
For this analysis, we are interested in knowing the number of eating places reachable within 5 minutes for every sport POI. We'll now proceed to calculate 5-minute isochrones for every POI, which represent the area reachable within 5 minutes.
You can read more regarding isochrones on CARTOframes Guides.
Step5:  Visualize isochrones
Step6:  <a id='section3'></a>
3. Enrich isochrones
We will now proceed to enrich our DataFrame. 
For enriching datasets, we use the Enrichment class. Please, visit CARTOframes Guides to learn more.
Step7:  <a id='section31'></a>
3.1 Simple enrichment
Step8:  Visualize enrichment
Step9:  <a id='section32'></a>
3.2 Enrichment applying filters
Step10:  Visualize enrichment
Step11:  <a id='section33'></a>
3.3 Brief analysis
Let's now take a look at how the total number of POI's and eating places around sport POI's correlate.
<ASSISTANT_TASK:>
Python Code:
import geopandas as gpd
import matplotlib.pyplot as plt
import seaborn as sns
from cartoframes.auth import set_default_credentials
from cartoframes.data.observatory import *
from cartoframes.data.services import Isolines
from cartoframes.viz import *
sns.set_style('whitegrid')
%matplotlib inline
Explanation: Advanced Data Enrichment using CARTO's Data Observatory
This notebook shows how to use CARTOframes to enrich the area of influence of different POIs with data from CARTO's Data Observatory. Please, visit CARTOframes Guides to learn more about the enrichment functionality.
We will show CARTOframes enrichment functionality with an example in which we will quantify the number of eating places within a 5-minute isochrone for all sports POI's in Madrid downtown.
The notebook is organized as follows:
1. Download sports POIs
2. Calculate isochrones
3. Enrich isochrones
 - Simple enrichment: Counting the number of POI's within isochrones
 - Enrichment applying filters: Counting the number of eating places
 - Brief analysis
Note for this notebook we are using the premium dataset of Pitney Bowes POI's in Spain.
Setup
Import packages
End of explanation
from cartoframes.auth import set_default_credentials
set_default_credentials('creds.json')
Explanation: Set CARTO default credentials
In order to be able to use the Data Observatory via CARTOframes, you need to set your CARTO account credentials first.
Please, visit the Authentication guide for further detail.
End of explanation
Catalog().subscriptions().datasets.to_dataframe()
pois_ds = Dataset.get('pb_points_of_i_94bda91b')
pois_ds.head()
sql_query = 
  SELECT * except(do_label) FROM $dataset$ 
  WHERE TRADE_DIVISION = 'DIVISION M. - SPORTS' 
  AND ST_IntersectsBox(geom, -3.716398,40.407437,-3.690477,40.425277)
pois_df = pois_ds.to_dataframe(sql_query=sql_query)
# To keep only the latest version of POI's
pois_df = pois_df.sort_values(['NAME', 'do_date']).groupby('NAME').first().reset_index()
pois_df.head()
Explanation: Note about credentials
For security reasons, we recommend storing your credentials in an external file to prevent publishing them by accident when sharing your notebooks. You can get more information in the section Setting your credentials of the Authentication guide.
<a id='section1'></a>
1. Download sports POIs
We need to start with the initial DataFrame that we would like to enrich. Normally, this initial DataFrame contains your own data that you later enrich with data from the Data Observatory. In this case, we will download all sports POI's and use it as our initial DataFrame.
We first check that we are subscribed to PB POIs dataset in Spain and download the sports POI's within a bounding box covering Madrid downtown. You can calculate your bounding box of interest using bboxfinder.
For a step by step description on how to discover and download premium datasets, take a look at templates: <a href='https://carto.com/developers/cartoframes/examples/#example-data-discovery-in-the-data-observatory' target='_blank'>Data Discovery</a> and <a href='https://carto.com/developers/cartoframes/examples/#example-access-premium-data-from-the-data-observatory' target='_blank'>Access Premium Data</a>.
End of explanation
iso_service = Isolines()
isochrones_gdf, isochrones_metadata = iso_service.isochrones(pois_df, [300], mode='walk', geom_col='geom')
isochrones_gdf.head()
pois_df['isochrone'] = isochrones_gdf.sort_values('source_id')['the_geom'].values
pois_df.head()
Explanation: <a id='section2'></a>
2. Calculate isochrones
For this analysis, we are interested in knowing the number of eating places reachable within 5 minutes for every sport POI. We'll now proceed to calculate 5-minute isochrones for every POI, which represent the area reachable within 5 minutes.
You can read more regarding isochrones on CARTOframes Guides.
End of explanation
Map([Layer(pois_df, geom_col='geom'),
     Layer(pois_df, geom_col='isochrone', style=basic_style(opacity=0.1))])
Explanation: Visualize isochrones
End of explanation
enrichment = Enrichment()
Explanation: <a id='section3'></a>
3. Enrich isochrones
We will now proceed to enrich our DataFrame. 
For enriching datasets, we use the Enrichment class. Please, visit CARTOframes Guides to learn more.
End of explanation
# Here we can use any variable because we're only interested in counts
pois_df = enrichment.enrich_polygons(
    pois_df,
    variables=['CLASS_517d6003'],
    aggregation='COUNT',
    geom_col='isochrone'
)
# We rename the column name to give it a more descriptive name
pois_df.rename(columns={'CLASS_y':'n_pois'}, inplace=True)
pois_df.head()
Explanation: <a id='section31'></a>
3.1 Simple enrichment: Counting the number of POI's within isochrones
We will start by simply counting the number of POI's within each isochrone. This will allow us to measure how busy the area around each sport POI is.
In order to do this, we will use the Enrichment function enrich_polygons() for which we can select any variable, because we are only interested in counting POIs. That is why we selected the variable CLASS_517d6003 that we will use later. Remember you can access the dataset variables doing pois_ds.variables.to_dataframe().
Note that we need to specify the name of the geometry column (geom_col) because we are working with a DataFrame instead of a GeoDataFrame.
End of explanation
Map(Layer(pois_df, geom_col='geom', 
          style=size_continuous_style('n_pois'),
          legends=size_continuous_legend('# POIs'),
          popup_hover=[popup_element('NAME', 'Name'), 
                        popup_element('n_pois', 'Number of POIs')]))
Explanation: Visualize enrichment
End of explanation
pois_df = enrichment.enrich_polygons(
    pois_df,
    variables=['CLASS_517d6003'],
    aggregation='COUNT',
    geom_col='iso_10walk',
    filters={Variable.get('CLASS_517d6003').id:"= 'EATING PLACES/RESTAURANTS'"}
)
# We rename the column name to give it a more descriptive name
pois_df.rename(columns={'CLASS':'n_pois_eating'}, inplace=True)
pois_df.head()
Explanation: <a id='section32'></a>
3.2 Enrichment applying filters: Counting the number of eating places
Now, we are interested in getting the number of eating places within a 5-minute isochrone for every sport POI. This requires using a filter to indicate that only eating places should be counted. Filters are added in a dictionary-like format, where the key is the filtering variable and the value is the filtering value.
If you are interested in knowing how to identify the variable to use as filter, check out this <a href='https://carto.com/developers/cartoframes/examples/#example-access-premium-data-from-the-data-observatory' target='_blank'>notebook</a> on how to access and download premium data.
End of explanation
Map(Layer(pois_df, geom_col='geom', 
          style=size_continuous_style('n_pois_eating'), 
          legends=size_continuous_legend('# Eating POIs'),
          popup_hover=[popup_element('NAME', 'Name'), 
                        popup_element('n_pois_eating', 'Number of eating places')]))
Explanation: Visualize enrichment
End of explanation
Layout([Map(Layer(pois_df, geom_col='geom', 
                  style=size_continuous_style('n_pois'),
                  legends=size_continuous_legend('# POIs'),
                  popup_hover=[popup_element('NAME', 'Name'), 
                               popup_element('n_pois', 'Number of POIs')])),
        Map(Layer(pois_df, geom_col='geom', 
                  style=size_continuous_style('n_pois_eating'), 
                  legends=size_continuous_legend('# Eating POIs'),
                  popup_hover=[popup_element('NAME', 'Name'), 
                               popup_element('n_pois_eating', 'Number of eating places')]))],
       map_height=550)
plt.figure(figsize=(12,5))
sns.regplot(pois_df['n_pois'], pois_df['n_pois_eating'], 
            scatter_kws={'color':'blue', 'alpha':0.5}, line_kws={'color':'red'})
Explanation: <a id='section33'></a>
3.3 Brief analysis
Let's now take a look at how the total number of POI's and eating places around sport POI's correlate.
End of explanation
<END_TASK>