<jupyter_start><jupyter_text>Step-by-step guide to generating an interactive climate map in Folium (& Geopandas)- **With some specific boilerplate code already filled in.** ---  - **CREDITS**:        This tutorial was prepared by [<NAME>](https://github.com/pawlodkowski) for the *Plotting on Maps* lesson @ Spiced Academy.        - **DATA**:     - The data for this particular lesson is **synthetic** / **fake!** It was originally scraped from [Berkeley Earth](http://berkeleyearth.lbl.gov/country-list/), but then regenerated based a simple polynomial trend and monthly seasonality modeled from the original data source & injected with random noise. Hence, the data in this repo is somewhat realistic but not authentic.- **INSTALLATION**:    - **Make sure you already have folium and geopandas installed**! (e.g. `pip` or `conda`), e.g.:        - `pip install folium`        - `pip install geopandas==0.8.0`     *Note*: this notebook was last run and tested on geopandas version 0.8.0 (released July 15, 2020). The latest version of folium should work just fine. ---  STEP 1: Read in historical temperature data<jupyter_code>DATA = '../data/temp_data.csv'
#Read in the data with pandas
import pandas as pd
df = pd.read_csv(DATA)<jupyter_output><empty_output><jupyter_text>------  STEP 2: Read in the geographic data (geometric shapes of all countries in the world) - Hint: Use GeoPandas    - What is a **Shape file (.shp)?**        - https://en.wikipedia.org/wiki/ShapefileShapefile_shape_format_(.shp)- Publicly available GIS data downloaded from *Natural Earth*: https://www.naturalearthdata.com/downloads/110m-cultural-vectors/<jupyter_code>SHAPEFILE = '../data/ne_110m_admin_0_countries.shp'
#Read in the shapefile with geopandas
import geopandas as gpd
gdf = gpd.read_file(____)<jupyter_output><empty_output><jupyter_text>*What happens if I have trouble installing geopandas*?- Unfortunately, this happened a couple times in the past with students, as the conda / pip installation on some Windows machines has been somewhat unreliable.    - In this case, there have been some helpful posts from StackOverflow (for example, [this one](https://stackoverflow.com/questions/54734667/error-installing-geopandas-a-gdal-api-version-must-be-specified-in-anaconda)), which finally got the installation working.- However, if you still have trouble with the installation despite lots of trial and error, you may consider creating a virtual environment or building a custom Docker image that builds off another image with Jupyter (e.g. https://hub.docker.com/r/jupyter/datascience-notebook)    - If you choose to go this route, please reach out to a teacher for help. - If you would rather not try those options (for very understandable reasons), then don't worry; a teacher can provide you with a `.geojson` file you can use.    - After all, the only reason we use GeoPandas in the first place is to read in the data and generate these GeoJSON files, so you shouldn't let this hold you back -- it's not that important in the end!     - Also, in general, with enough time spent googling around, you can find GeoJSON files from pretty much everywhere! For example:        - https://github.com/johan/world.geo.json/tree/master/countries        - https://github.com/isellsoap/deutschlandGeoJSON/blob/master/2_bundeslaender/4_niedrig.geo.json        - https://github.com/funkeinteraktiv/Berlin-Geodaten/blob/master/berlin_bezirke.geojson        - _And many more! They're super easy to find online! The world of open source is truly wonderful..._ ------  STEP 3: Group / aggregate the temperature anomaly data by country, year- For simplicity, we're only interested in yearly averages<jupyter_code>df.groupby(...)<jupyter_output><empty_output><jupyter_text>STEP 4: Merge Data Sets.- We want to have our temperature data and geometric data in one place.- **Make sure you're still left with a GeoDataFrame at the end!**    - otherwise, if the resulting object is a regular Pandas dataframe, the ``.to_json()`` export will produce a normal ``.json`` file rather than a specialized ``.geojson`` file.    - A geojson file is very similar to a json file, with the exception that it's a bit more strict and specialized and works better with plotting libraries that usually expect the data to be in that format.<jupyter_code>gdf.merge(...)<jupyter_output><empty_output><jupyter_text>------ Time for Visualization with Folium ------  STEP 5: Plot data on a map for a single year (we can make it interactive later)     5a. Generate a blank canvas / figure.<jupyter_code>import folium
basemap = folium.Map(location=[52.54, 13.36],
                zoom_start=2,
                tiles='CartoDB positron') #try out the other options!
basemap #display the map directly in Jupyter!<jupyter_output><empty_output><jupyter_text>5a. Generate a GeoJSON string for a single year.- The Folium library (as well as many other JavaScript-based mapping libraries) requires the data to be in GeoJSON format.    - **HINT**: How can you convert a GeoDataFrame into a GeoJSON? Think of how you might do this in regular pandas.- Let's use the year 2000 as an example.<jupyter_code>gdf_2000 = gdf[gdf['___'] == ___]
json_2000 = gdf_2000.to____()<jupyter_output><empty_output><jupyter_text>STEP 6: Generate an interactive choropleth map of the data for a single year- Use the convenient ``folium.Choropleth()`` class to generate interactive tiles, which we can overlay on top of our base map!- The trick to get it working is to make sure that the Choropleth layer understands which column from the dataframes is supposed to be mapped to which key in the JSON string in order for the data to render properly.<jupyter_code>tiles = folium.Choropleth(
            geo_data=____,                          # geojson string that includes the geo data (for the year 2000)
            name="____",
            data=____,                              # dataframe that includes the data (for the year 2000)
            columns=["country", "monthly_anomaly"], # names of the columns to include from the dataframe
            key_on="properties._____",              # name of JSON key within the "properties" value that contains country names
            fill_color="YlOrRd",                    # play around with the rest of the aesthetic options
            nan_fill_color="#ededed",         
            fill_opacity=0.7,
            line_opacity=0.2,
            legend_name="Monthly Temperature Anomaly",
            highlight=True,
        )
tiles.add_to(basemap) #add the layer to the blank canvas / figure
# basemap<jupyter_output><empty_output><jupyter_text>STEP 7: Add additional features to the map!Some ideas:- **Tooltip highlighting** (included here)- Adding other layers / markers- Making the tiles "clickable"- Make the legend a fixed size- The documentation isn't *great*, but with enough persistence / looking at examples online (some pretty good tutorials out there) / reading forums, you can add nice little widgets and extra interactivity to your map!<jupyter_code>style_html = "font-size: 10px; font-weight: normal" #add a little bit of HTML, if you know some.

tooltip = folium.features.GeoJsonTooltip(fields = ['country', 'monthly_anomaly'],
                                         style = style_html) 

tiles.geojson.add_child(tooltip)
#overwrite some of the original properties of the geojson attribute of the tile
basemap #the map should now display information whenever you hover over a country tile!<jupyter_output><empty_output><jupyter_text>STEP 8: Export the figure to an HTML file, so you can open it in your web browser!- The reason the figure is interactive (e.g. you can zoom around, it has hover effects, etc.) is because there's a of front-end (i.e. client-side) JavaScript code that Plotly creates for you automatically.- Use the ``.save()`` method to export the file and open it up in a web browser.    - Bonus: Open the ``.html`` file in a text editor and see if you can understand any of it :)<jupyter_code>basemap.save("2000_map.html")
#bash command to open the file (should use your web browser by default)
!open 2000_map.html<jupyter_output><empty_output>
{'fraction_non_alphanumeric': 0.08596340415080438, 'fraction_numerical': 0.01056121822424168, 'mean_word_length': 3.7597895967270603, 'pattern_counts': {'":': 0, '<': 38, '<?xml version=': 0, '>': 38, 'https://': 8, 'lorem ipsum': 0, 'www.': 1, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 4, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'chain_length': '9', 'dir': 'jupyter-structured-clean-dedup', 'id': '262767', 'license': 'MIT', 'n_tokens_mistral': 2364, 'n_tokens_neox': 2212, 'n_words': 972, 'path': 'folium/folium_tutorial.ipynb', 'repo_name': 'lenaromanenko/interactive_climate_map', 'size': '8152'}