Exemplo n.º 1
0
def test_timedynamic_geo_json():
    """
    tests folium.plugins.TimeSliderChoropleth
    """
    import geopandas as gpd
    assert 'naturalearth_lowres' in gpd.datasets.available
    datapath = gpd.datasets.get_path('naturalearth_lowres')
    gdf = gpd.read_file(datapath)

    n_periods = 3
    dt_index = pd.date_range('2016-1-1', periods=n_periods, freq='M').strftime('%s')

    styledata = {}

    for country in gdf.index:
        pdf = pd.DataFrame(
            {'color': np.random.normal(size=n_periods),
             'opacity': np.random.normal(size=n_periods)},
            index=dt_index)
        styledata[country] = pdf.cumsum()

    max_color, min_color = 0, 0

    for country, data in styledata.items():
        max_color = max(max_color, data['color'].max())
        min_color = min(max_color, data['color'].min())

    cmap = linear.PuRd_09.scale(min_color, max_color)

    # Define function to normalize column into range [0,1]
    def norm(col):
        return (col - col.min())/(col.max()-col.min())

    for country, data in styledata.items():
        data['color'] = data['color'].apply(cmap)
        data['opacity'] = norm(data['opacity'])

    styledict = {str(country): data.to_dict(orient='index') for
                 country, data in styledata.items()}

    m = folium.Map((0, 0), tiles='Stamen Watercolor', zoom_start=2)

    time_slider_choropleth = TimeSliderChoropleth(
        gdf.to_json(),
        styledict
    )
    time_slider_choropleth.add_to(m)

    rendered = time_slider_choropleth._template.module.script(time_slider_choropleth)

    m._repr_html_()
    out = m._parent.render()
    assert '<script src="https://d3js.org/d3.v4.min.js"></script>' in out

    # We verify that data has been inserted correctly
    expected_timestamps = """var timestamps = ["1454198400", "1456704000", "1459382400"];"""  # noqa
    assert expected_timestamps.split(';')[0].strip() == rendered.split(';')[0].strip()

    expected_styledict = json.dumps(styledict, sort_keys=True, indent=2)
    assert expected_styledict in rendered
def test_timedynamic_geo_json():
    """
    tests folium.plugins.TimeSliderChoropleth
    """
    import geopandas as gpd
    assert 'naturalearth_lowres' in gpd.datasets.available
    datapath = gpd.datasets.get_path('naturalearth_lowres')
    gdf = gpd.read_file(datapath)

    n_periods = 3
    dt_index = pd.date_range('2016-1-1', periods=n_periods, freq='M').strftime('%s')

    styledata = {}

    for country in gdf.index:
        pdf = pd.DataFrame(
            {'color': np.random.normal(size=n_periods),
             'opacity': np.random.normal(size=n_periods)},
            index=dt_index)
        styledata[country] = pdf.cumsum()

    max_color, min_color = 0, 0

    for country, data in styledata.items():
        max_color = max(max_color, data['color'].max())
        min_color = min(max_color, data['color'].min())

    cmap = linear.PuRd_09.scale(min_color, max_color)

    # Define function to normalize column into range [0,1]
    def norm(col):
        return (col - col.min())/(col.max()-col.min())

    for country, data in styledata.items():
        data['color'] = data['color'].apply(cmap)
        data['opacity'] = norm(data['opacity'])

    styledict = {str(country): data.to_dict(orient='index') for
                 country, data in styledata.items()}

    m = folium.Map((0, 0), tiles='Stamen Watercolor', zoom_start=2)

    time_slider_choropleth = TimeSliderChoropleth(
        gdf.to_json(),
        styledict
    )
    time_slider_choropleth.add_to(m)

    rendered = time_slider_choropleth._template.module.script(time_slider_choropleth)

    m._repr_html_()
    out = m._parent.render()
    assert '<script src="https://d3js.org/d3.v4.min.js"></script>' in out

    # We verify that data has been inserted correctly
    expected_timestamps = """var timestamps = ["1454198400", "1456704000", "1459382400"];"""  # noqa
    assert expected_timestamps.split(';')[0].strip() == rendered.split(';')[0].strip()

    expected_styledict = json.dumps(styledict, sort_keys=True, indent=2)
    assert expected_styledict in rendered
Exemplo n.º 3
0
def create_gdp_viz():
    '''
    Load and pre-process the geojson file
    '''
    geojson_path = os.path.normpath(
        os.path.join(script_dir_path, '..', 'data', 'borders_geo.json'))
    world_geojson = gpd.read_file(geojson_path)
    world_geojson.drop(columns=['ISO_A2', 'ADMIN'], inplace=True)
    world_geojson.drop(world_geojson[world_geojson['ISO_A3'] == '-99'].index,
                       inplace=True)
    country_list = world_geojson['ISO_A3'].tolist()
    '''
    Load and pre-process the GDP data
    '''
    # Load the GDP data
    df_GDP_path = os.path.normpath(
        os.path.join(script_dir_path, '..', 'data',
                     'GDP_per_capita_world_data.csv'))
    df_GDP = pd.read_csv(df_GDP_path, index_col='Country Code', skiprows=4)

    # Drop unnecessary data
    df_GDP.drop(labels='2020', axis=1, inplace=True)

    csv_country_list = df_GDP.index.tolist()
    country_list = list(set(country_list).intersection(csv_country_list))
    df_GDP.drop(df_GDP[~df_GDP.index.isin(country_list)].index, inplace=True)
    world_geojson.drop(
        world_geojson[~world_geojson['ISO_A3'].isin(country_list)].index,
        inplace=True)
    country_list.sort()

    # Create an enumerated country dict for id mapping
    country_dict = {k: v for v, k in enumerate(country_list)}
    world_geojson['country_id'] = world_geojson['ISO_A3'].map(country_dict)

    # Count min and max GDP values
    min_GDP_val, max_GDP_val = df_GDP[df_GDP.columns[4:]].min().min(), df_GDP[
        df_GDP.columns[4:]].max().max()

    # Create a color list
    color_list = [
        '#808080', '#A50026', '#D73027', '#F46D43', '#FDAE61', '#FEE08B',
        '#FFFFBF', '#D9EF8B', '#A6D96A', '#66BD63', '#1A9850', '#006837'
    ]

    # Create a list of geometrically spaced numbers over a min-max interval
    bins = np.geomspace(min_GDP_val, max_GDP_val, 12)

    # Replace NaNs (records with no data available) with '-1'
    df_GDP.fillna(-1, inplace=True)

    # Add NaN category to the bins
    bins = np.insert(bins, 0, -1.)
    bins = bins.tolist()

    # Append 'color_[year]' columns to the GDP DataFrame
    year = 1960
    while year <= 2019:
        pasted_col_id = df_GDP.columns.get_loc(str(year)) + 1
        col_value = pd.cut(df_GDP[str(year)],
                           bins,
                           include_lowest=True,
                           labels=[
                               '#808080', '#A50026', '#D73027', '#F46D43',
                               '#FDAE61', '#FEE08B', '#FFFFBF', '#D9EF8B',
                               '#A6D96A', '#66BD63', '#1A9850', '#006837'
                           ])
        df_GDP.insert(loc=pasted_col_id,
                      column='color_' + str(year),
                      value=col_value)
        year += 1

    print(df_GDP)
    '''
    Create appropriately formatted dictionary that the TimeSliderChoropleth will receive as an input
    '''
    gdp_dict = {}
    for country_code in df_GDP.index.tolist():
        country_id = str(country_dict[country_code])
        gdp_dict[country_id] = {}
        year = 1960
        while year <= 2019:
            dt_obj = datetime(year=year, month=12, day=31)
            year_in_ms = str(time.mktime(dt_obj.timetuple()))
            color_hex = df_GDP.at[country_code, 'color_' + str(year)]
            gdp_dict[country_id][year_in_ms] = {
                'color': color_hex,
                'opacity': 0.7
            }
            year += 1
    ''' 
    Initialize the map
    '''
    map_GDP = folium.Map(location=[0, 0],
                         zoom_start=4,
                         max_bounds=True,
                         min_zoom=3)
    '''
    Create the map content and add it to the map object
    '''
    # Create the choropleth
    choropleth = TimeSliderChoropleth(
        world_geojson.set_index('country_id').to_json(), styledict=gdp_dict)
    choropleth.add_to(map_GDP)

    # Create the map legend
    legend_labels_dict = {}
    i = 0
    for color in color_list:
        if i == 0:
            legend_labels_dict[color_list[i]] = 'No data'
        elif i == len(color_list) - 1:
            legend_labels_dict[color_list[i]] = '> ' + str(round(bins[i],
                                                                 2)) + '$'
            break
        else:
            legend_labels_dict[color] = str(round(
                bins[i], 2)) + '$' + ' - ' + str(round(bins[i + 1], 2)) + '$'
        i += 1

    template = utils.create_legend(caption='GDP per capita in USD',
                                   legend_labels=legend_labels_dict)
    macro = MacroElement()
    macro._template = Template(template)
    map_GDP.get_root().add_child(macro)
    '''
    Save completed map viz to an appropriate folder
    '''
    map_GDP.save(
        os.path.join(script_dir_path, '..', 'webapp', 'templates',
                     'GDP_viz.html'))
    print('Successfully created the GDP viz!')