Beispiel #1
0
def getIMR(data, current_year):
    # Create the plot
    #Input GeoJSON source that contains features for plotting.
    geosource = GeoJSONDataSource(geojson=json.dumps(data))
    #Define a sequential multi-hue color palette.
    palette = brewer['YlGnBu'][8]
    #Reverse color order so that dark blue is highest value.
    palette = palette[::-1]
    #Instantiate LinearColorMapper that linearly maps numbers in a range, into a sequence of colors. Input nan_color.
    color_mapper = LinearColorMapper(palette=palette,
                                     low=0,
                                     high=56,
                                     nan_color='#d9d9d9')
    #Define custom tick labels for color bar.
    tick_labels = {
        '0': '0',
        '7': '7',
        '14': '14',
        '21': '21',
        '28': '28',
        '35': '35',
        '42': '42',
        '49': '49',
        '56': '56'
    }
    #Add hover tool
    hover_IMR = HoverTool(
        tooltips=[('Year',
                   '@Year'), ('State/UT',
                              '@State'), ('Infant Mortality Rate', '@IMR')])
    #Create color bar.
    color_bar = ColorBar(color_mapper=color_mapper,
                         label_standoff=7,
                         width=400,
                         height=20,
                         border_line_color=None,
                         location=(0, 0),
                         orientation='horizontal',
                         major_label_overrides=tick_labels)
    #Create figure object for IMR.
    p_IMR = figure(title='Infant Mortality Rate - ' + str(current_year),
                   plot_height=600,
                   plot_width=450,
                   toolbar_location=None,
                   tools=[hover_IMR])
    p_IMR.xgrid.grid_line_color = None
    p_IMR.ygrid.grid_line_color = None
    p_IMR.axis.visible = False
    #Add patch renderer to figure.
    p_IMR.patches('xs',
                  'ys',
                  source=geosource,
                  fill_color={
                      'field': 'IMR',
                      'transform': color_mapper
                  },
                  line_color='black',
                  line_width=0.25,
                  fill_alpha=1)
    #Specify layout
    p_IMR.add_layout(color_bar, 'below')
    curdoc().add_root(p_IMR)
    return (p_IMR)
Beispiel #2
0
def lisa_cluster(moran_loc,
                 df,
                 p=0.05,
                 region_column='',
                 title=None,
                 plot_width=500,
                 plot_height=500,
                 tools=''):
    '''
    Lisa Cluster map, coloured by local spatial autocorrelation

    Parameters
    ----------
    moran_loc : esda.moran.Moran_Local instance
        values of Moran's Local Autocorrelation Statistic
    df : geopandas dataframe instance
        In mask_local_auto(), assign df['labels'] per row. Note that
        ``df`` will be modified, so calling functions uses a copy of
        the user provided ``df``.
    p : float, optional
        The p-value threshold for significance. Points will
        be colored by significance.
    title : str, optional
        Title of map. Default title=None
    plot_width : int, optional
        Width dimension of the figure in screen units/ pixels.
        Default = 500
    plot_height : int, optional
        Height dimension of the figure in screen units/ pixels.
        Default = 500

    Returns
    -------
    fig : Bokeh figure instance
        Figure of LISA cluster map, colored by local spatial autocorrelation

    Examples
    --------
    >>> import libpysal.api as lp
    >>> from libpysal import examples
    >>> import geopandas as gpd
    >>> from esda.moran import Moran_Local
    >>> from splot.bk import lisa_cluster
    >>> from bokeh.io import show

    >>> link = examples.get_path('columbus.shp')
    >>> df = gpd.read_file(link)
    >>> y = df['HOVAL'].values
    >>> w = lp.Queen.from_dataframe(df)
    >>> w.transform = 'r'
    >>> moran_loc = Moran_Local(y, w)

    >>> TOOLS = "tap,reset,help"
    >>> fig = lisa_cluster(moran_loc, df, p=0.05, tools=TOOLS)
    >>> show(fig)
    '''
    # We're adding columns, do that on a copy rather than on the users' input
    df = df.copy()

    # add cluster_labels and colors5 in mask_local_auto
    cluster_labels, colors5, _, labels = mask_local_auto(moran_loc, p=0.05)
    df['labels_lisa'] = labels
    df['moranloc_psim'] = moran_loc.p_sim
    df['moranloc_q'] = moran_loc.q

    # load df into bokeh data source
    geo_source = GeoJSONDataSource(geojson=df.to_json())

    fig = _lisa_cluster_fig(geo_source,
                            moran_loc,
                            cluster_labels,
                            colors5,
                            bounds=df.total_bounds,
                            region_column=region_column,
                            title=title,
                            plot_width=plot_width,
                            plot_height=plot_height,
                            tools=tools)
    return fig
Beispiel #3
0
def build_time_evolution_tab():

    # Importing geographical shapefile
    s3_root = 'https://covid19-bokeh-app.s3.eu-west-2.amazonaws.com'

    geo_data_gdf = gpd.read_file(f'{s3_root}/data/_geo_data/ne_50m_land.zip')

    geosource = GeoJSONDataSource(geojson=geo_data_gdf.to_json())

    # Importing geo-evolutions cases/deaths data
    time_evol_df = pd.read_csv(f'{s3_root}/data/geo_time_evolution.csv')

    # Selecting earliest snapshot
    time_evol_df.date = pd.to_datetime(time_evol_df.date, format="%Y-%m-%d")

    snapshot_df = time_evol_df[time_evol_df.date == min(time_evol_df.date)]

    global_by_day_df = pd.read_csv(f'{s3_root}/data/global_by_day.csv')

    global_by_day_df.date = pd.to_datetime(global_by_day_df.date,
                                           format="%Y-%m-%d")
    global_totals_df = global_by_day_df.loc[global_by_day_df.date == min(
        time_evol_df.date)]
    global_cases = int(global_totals_df.iloc[0]['cases'])
    global_deaths = int(global_totals_df.iloc[0]['deaths'])

    # Applying bubble-size mapping
    bubble_size = snapshot_df['cases'].apply(lambda x: 0.5 * math.log(x, 1.1)
                                             if x > 0 else 0)
    snapshot_df = snapshot_df.assign(size=bubble_size.values)

    # Creating ColumnDataSource for visualisation
    cases_cds = ColumnDataSource(snapshot_df)

    # Adding figure and geographical patches from shapefile
    geo_plot = figure(plot_height=450,
                      plot_width=720,
                      x_range=(-180, 180),
                      y_range=(-90, 90),
                      name="time_evolution_geo_plot",
                      sizing_mode="scale_width")

    geo_patches = geo_plot.patches('xs', 'ys', source=geosource, alpha=0.5)

    # Adding circle glyph to create bubble plot
    cases_circles = geo_plot.circle(x='long',
                                    y='lat',
                                    size='size',
                                    source=cases_cds,
                                    color='red',
                                    alpha=0.2)

    # Adding hover tool
    hover = HoverTool(tooltips=[('Country/Region', '@region'),
                                ('Province/State', '@province'),
                                ('Cases', '@cases')],
                      renderers=[cases_circles])
    geo_plot.add_tools(hover)

    # Adding hbar
    countries_df = snapshot_df.loc[:, ['date', 'region', 'cases']]

    countries_df.rename(columns={"cases": "value"}, inplace=True)

    countries_df = countries_df.groupby(['date', 'region']).sum().reset_index()

    countries_df.sort_values(by='value', ascending=False, inplace=True)
    countries_df = countries_df.reset_index(drop=True)
    countries_cds = ColumnDataSource(countries_df)

    hbar_plot = figure(plot_height=450,
                       plot_width=475,
                       y_range=(10.5, -0.5),
                       x_range=(0, countries_df.value.max() * 1.2),
                       name="time_evolution_hbar_plot",
                       sizing_mode="scale_width")

    hbar = hbar_plot.hbar(left=0,
                          right='value',
                          y='index',
                          source=countries_cds,
                          height=0.5,
                          line_color='white')

    labels = LabelSet(x='value',
                      y='index',
                      text='region',
                      text_font_size='10pt',
                      text_color='white',
                      x_offset=5,
                      y_offset=0,
                      source=countries_cds,
                      level='glyph',
                      render_mode='canvas')

    hbar_plot.add_layout(labels)

    # Adding hover tool
    hover_hbar = HoverTool(tooltips=[('Country/Region', '@region'),
                                     ('Cases', '@value')],
                           renderers=[hbar])
    hbar_plot.add_tools(hover_hbar)

    # Adding callback for updating data
    def data_view_callback(attr, old, new):
        """Callback function to update data source:

            - Updates source data to selected data view
              (cases/deaths/new cases/new deaths)
              and selected snapshot date on date slider.

            - Updates HoverTool to reflect data view change

            - Updates Divs for total cases/deaths
        """

        # Determine data view selection
        if cases_deaths_button.active == 0:
            data_view = "cases"
        elif cases_deaths_button.active == 1:
            data_view = "deaths"

        if total_new_button.active == 1:
            data_view = f"new_{data_view}"

        # Determine date selection
        slider_date = date_slider.value_as_datetime.date()

        # Filter data for selected date
        snapshot_df = time_evol_df[time_evol_df.date == pd.Timestamp(
            slider_date)]

        # Map bubble size on selected data view
        bubble_size = snapshot_df[data_view].apply(
            lambda x: 0.5 * math.log(x, 1.1) if x > 0 else 0)
        snapshot_df = snapshot_df.assign(size=bubble_size.values)

        cases_cds.data = snapshot_df

        hover.tooltips = [('Country/Region', '@region'),
                          ('Province/State', '@province'),
                          (data_view.replace('_',
                                             ' ').title(), f'@{data_view}')]

        # Update hbar data
        countries_df = snapshot_df.loc[:, ['date', 'region', data_view]]
        countries_df.rename(columns={data_view: "value"}, inplace=True)

        countries_df = countries_df.groupby(['date',
                                             'region']).sum().reset_index()

        countries_df.sort_values(by="value", ascending=False, inplace=True)
        countries_df = countries_df.reset_index(drop=True)
        countries_cds.data = countries_df

        hbar_plot.x_range.end = countries_df.value.max() * 1.2

        hover_hbar.tooltips = [('Country/Region', '@region'),
                               (data_view.replace('_', ' ').title(), '@value')]

        # Filter for totals
        global_totals_df = global_by_day_df.loc[(
            global_by_day_df.date == pd.Timestamp(slider_date))]
        global_cases = int(global_totals_df.iloc[0]['cases'])
        global_deaths = int(global_totals_df.iloc[0]['deaths'])

        cases_div.text = (f'<h3 class="card-text">' f'{global_cases:,}</h3>')

        deaths_div.text = (f'<h3 class="card-text">' f'{global_deaths:,}</h3>')

    # Adding Date slider
    date_range = [
        pd.Timestamp(date_val) for date_val in time_evol_df.date.unique()
    ]

    date_slider = DateSlider(title="Date",
                             start=min(date_range),
                             end=max(date_range),
                             value=min(date_range),
                             sizing_mode="scale_width")
    date_slider.on_change('value', data_view_callback)

    # Adding Cases/Deaths toggle
    cases_deaths_button = RadioButtonGroup(labels=["Cases", "Deaths"],
                                           active=0,
                                           sizing_mode="scale_width")
    cases_deaths_button.on_change('active', data_view_callback)

    # Adding Total/New toggle
    total_new_button = RadioButtonGroup(labels=["Total", "New"],
                                        active=0,
                                        sizing_mode="scale_width")
    total_new_button.on_change('active', data_view_callback)

    # Adding callback for zooming into a selected continent
    def continent_zoom_callback(attr, old, new):

        continent_map_ref = {
            # Worldwide
            0: {
                'x_range': [-200, 200],
                'y_range': [-100, 100]
            },
            # Europe
            1: {
                'x_range': [-30, 50],
                'y_range': [30, 70]
            },
            # North America
            2: {
                'x_range': [-175, -15],
                'y_range': [0, 80]
            },
            # South America
            3: {
                'x_range': [-140, 10],
                'y_range': [-60, 15]
            },
            # Africa
            4: {
                'x_range': [-55, 105],
                'y_range': [-40, 40]
            },
            # Asia
            5: {
                'x_range': [40, 140],
                'y_range': [-5, 45]
            },
            # Oceania
            6: {
                'x_range': [80, 200],
                'y_range': [-55, 5]
            }
        }

        map_ref = continent_map_ref[continent_button.active]
        geo_plot.x_range.start = map_ref['x_range'][0]
        geo_plot.x_range.end = map_ref['x_range'][1]
        geo_plot.y_range.start = map_ref['y_range'][0]
        geo_plot.y_range.end = map_ref['y_range'][1]

    # Adding continent toggle
    continent_button = RadioGroup(labels=[
        "Worldwide", "Europe", "North America", "South America", "Africa",
        "Asia", "Oceania"
    ],
                                  active=0)
    continent_button.on_change('active', continent_zoom_callback)

    # Adding animation with Play/Pause button
    callback_id = None

    def animate():
        def animate_update():
            date = date_slider.value_as_datetime.date() + timedelta(days=1)
            date = pd.Timestamp(date)
            if date >= max(date_range):
                date = min(date_range)
            date_slider.value = date

        global callback_id
        if play_button.label == '► Play':
            play_button.label = '❚❚ Pause'
            callback_id = curdoc().add_periodic_callback(animate_update, 300)
        else:
            play_button.label = '► Play'
            curdoc().remove_periodic_callback(callback_id)

    play_button = Button(label='► Play', width=60, button_type="success")
    play_button.on_click(animate)

    # Adding Cases/Deaths count
    cases_div = Div(text=f'<h3 class="card-text">'
                    f'{global_cases:,}</h3>',
                    sizing_mode="scale_width",
                    name="cases_div")

    deaths_div = Div(text=f'<h3 class="card-text">'
                     f'{global_deaths:,}</h3>',
                     sizing_mode="scale_width",
                     name="deaths_div")

    # Defining layout of tab
    widgets = widgetbox(date_slider,
                        cases_deaths_button,
                        total_new_button,
                        play_button,
                        continent_button,
                        name="time_evolution_widgetbox",
                        sizing_mode="scale_width")

    # Add the plot to the current document
    curdoc().add_root(geo_plot)
    curdoc().add_root(hbar_plot)
    curdoc().add_root(widgets)

    curdoc().add_root(cases_div)
    curdoc().add_root(deaths_div)
Beispiel #4
0
from bokeh.plotting import figure
from bokeh.sampledata.sample_geojson import geojson as original

updated = json.dumps({
    'type': 'FeatureCollection',
    'features': [{
        "type": "Feature",
        "geometry": {
            "type": "Point",
            "coordinates": [-2.1208465099334717, 51.4613151550293]
        },
        "properties": {"OrganisationCode": "Q64"}
    }]
})

source = GeoJSONDataSource(geojson=original)

p = figure(tools='box_select')
p.circle(x='x', y='y', line_color=None, fill_alpha=0.8, source=source)

# open a session to keep our local document in sync with server
session = push_session(curdoc())

@repeat([0,1])
def update(i):
    # alternate between original/updated
    source.geojson = [original, updated][i]

curdoc().add_periodic_callback(update, 100)

session.show() # open the document in a browser
Beispiel #5
0
from bokeh.plotting import save, figure
from bokeh.models import GeoJSONDataSource

addresses_fp = r"C:\Users\oyeda\Desktop\AUTOGIS\AUTOGIS_PERIOD2\assignment5\data\addresses.shp"
roads_fp = r"C:\Users\oyeda\Desktop\AUTOGIS\AUTOGIS_PERIOD2\assignment5\data\roads.shp"

# Read the data
addresses = gpd.read_file(addresses_fp)
roads = gpd.read_file(roads_fp)

# Reproject to the same projection
CRS = roads.crs
addresses = addresses.to_crs(crs=CRS)

# Convert GeoDataFrames into GeoJSONDataSource objects (similar to ColumnDataSource)
point_source = GeoJSONDataSource(geojson=addresses.to_json())
roads_source = GeoJSONDataSource(geojson=roads.to_json())

# Initialize our plot figure
p = figure(title="A test map")

# Add the lines to the map from our GeoJSONDataSource -object (it is important to specify the columns as 'xs' and 'ys')
p.multi_line('xs', 'ys', source=roads_source, color='gray', line_width=3)

# Add the lines to the map from our 'msource' ColumnDataSource -object
p.circle('x', 'y', source=point_source, color='black', size=6)

# Output filepath
outfp = r"C:\Users\oyeda\Desktop\AUTOGIS\AUTOGIS_PERIOD2\assignment5\solution\test_map.html"

# Save the map
Beispiel #6
0
# STEP 4: Merge Data Sets.
gdf = pd.merge(left=gdf,
               right=df,
               left_on='ADMIN',
               right_on='country',
               how='inner')


def get_geojson(year):
    """Input a year (int) and return corresponding GeoJSON"""
    gdf_year = gdf[gdf['year'] == year]
    return gdf_year.to_json()


geosource = GeoJSONDataSource(geojson=get_geojson(2000))

# STEP 5: Plot data on a map for a single year.
# 5a. Generate a blank canvas / figure.
p = figure(
    title='Average temperature anomaly of countries over time',
    plot_height=600,
    plot_width=1000,
)

palette = brewer['YlGn'][5]

color_mapper = LinearColorMapper(palette=palette,
                                 low=-2.4,
                                 high=4,
                                 nan_color=palette[2])
def get_figure(year: int):
    '''
    create bokeh figure object
    :param year: year
    :return: figure
    '''
    df_year = df[df['year'] == year]
    # Merge dataframes gdf and df_2016.
    merged = gdf.merge(df_year, left_on='country_code', right_on='code')

    # Read data to json.
    merged_json = json.loads(merged.to_json())
    # Convert to String like object.
    json_data = json.dumps(merged_json)

    # Input GeoJSON source that contains features for plotting.
    geosource = GeoJSONDataSource(geojson=json_data)
    # Define a sequential multi-hue color palette.
    palette = brewer['RdBu'][11]
    # Reverse color order so that dark blue is highest obesity.
    # Instantiate LinearColorMapper that linearly maps numbers in a range, into a sequence of colors.
    color_mapper = LinearColorMapper(palette=palette, low=-2, high=2)
    # Define custom tick labels for color bar.
    tick_labels = {
        '0': '0°C',
        '-0.5': '-0.5°C',
        '-1': '-1°C',
        '-1.5': '-1.5°C',
        '-2': '-2°C',
        '0.5': '0.5°C',
        '1': '1°C',
        '1.5': '1.5°C',
        '2': '2°C'
    }
    # Create color bar.
    color_bar = ColorBar(color_mapper=color_mapper,
                         label_standoff=8,
                         width=500,
                         height=20,
                         border_line_color=None,
                         location=(0, 0),
                         orientation='horizontal',
                         major_label_overrides=tick_labels)
    # Create figure object.
    p = figure(title='Surface temperature anomaly (degrees celcius), ' +
               str(year),
               plot_height=600,
               plot_width=950,
               toolbar_location=None)
    p.xgrid.grid_line_color = None
    p.ygrid.grid_line_color = None
    # Add patch renderer to figure.
    p.patches('xs',
              'ys',
              source=geosource,
              fill_color={
                  'field': 'temperature',
                  'transform': color_mapper
              },
              line_color='black',
              line_width=0.25,
              fill_alpha=1)
    # Specify figure layout.
    p.add_layout(color_bar, 'below')
    return p
Beispiel #8
0
def make_map(zipcodes_to_plot='60608',
             num_neighbor=3,
             period_str='midday',
             cate=[]):
    """
    input: updated parameters selected by users
    output: updated visualization of nearby neighbors
    """
    with open('chi-zip-code-tabulation-areas-2012.geojson', 'rt') as json_file:
        chi_json = json.load(json_file)
    chi_json['features'][
        zipcodes[zipcodes_to_plot]]['properties']['color_type'] = 2

    chi_zipcode_to_dist = pd.read_pickle('chi_zipcode_to_dist_' + period_str)

    # for an updated period, check the shared zip codes with geojson
    shared_zips = collections.defaultdict(int)
    for zipcode in chi_zipcode_to_dist:
        shared_zips[zipcode] += 1
    for zipcode in zipcodes:
        shared_zips[zipcode] += 1


# if a zip code exists in both geojson file and hood2vec statistical file, then "YES", we can visualize it. Otherwise, "NO"
    for zipcode in zipcodes:
        if shared_zips[zipcode] == 2:
            chi_json['features'][
                zipcodes[zipcode]]['properties']['has_data'] = 'YES'
        else:
            chi_json['features'][
                zipcodes[zipcode]]['properties']['has_data'] = 'NO'

    # if user selects to visualize neighbors in venue type representation
    if cate == [0]:
        period_str = 'category'

    chi_zipcode_to_dist = pd.read_pickle('chi_zipcode_to_dist_' + period_str)

    # if closest zip codes are also in geojson file, we can visualize it. We set them to a lighter color "1"
    distances = chi_zipcode_to_dist[zipcodes_to_plot]
    num_neighbor_count = 0
    for neighbor_idx in range(len(distances)):
        if shared_zips[distances[neighbor_idx][0]] == 2:
            num_neighbor_count += 1
            chi_json['features'][zipcodes[distances[neighbor_idx]
                                          [0]]]['properties']['color_type'] = 1
        if num_neighbor_count == num_neighbor:
            break

    geojson = json.dumps(chi_json)
    geo_source = GeoJSONDataSource(geojson=geojson)

    color_mapper = LinearColorMapper(palette=Viridis6)
    p = figure(title="Chicago",
               #                    tools=TOOLS,\
               #                    x_axis_location=None, y_axis_location=None,\
               #                    x_range=(-9780000, -9745000), y_range=(5130000, 5160000),
               x_axis_type="mercator", y_axis_type="mercator",\
              )
    p.axis.visible = False
    p.grid.grid_line_color = None
    #         https://bokeh.pydata.org/en/latest/docs/reference/tile_providers.html
    #         p.add_tile(get_provider(Vendors.STAMEN_TERRAIN))
    #         p.add_tile(CARTODBPOSITRON)
    p.grid.grid_line_color = None
    p.patches(
        'xs',
        'ys',
        fill_alpha=0.7,
        fill_color={
            'field': 'color_type',
            'transform': color_mapper
        },
        source=geo_source,
    )

    # information to hover
    hover = HoverTool(tooltips=[('Zip Code', '@ZIP'), ('Has Data',
                                                       '@has_data')])
    p.add_tools(hover)

    # return the handler p to pass updated values to visualization
    return p
Beispiel #9
0
# For each date, extract a list of daily new cases per capita from all cantons(e.g. 'AG_diff_pc', 'AI_diff_pc', etc.), and add as a new column in merged
# For instance, in the column['2020-10-31'], there are: [0.0005411327220155498, nan, nan, 0.000496300306803826, ...]
list_diff_pc = case_raw.loc[:, case_raw.columns.str.contains('diff_pc')]
list_diff_pc = list_diff_pc.drop(columns='CH_diff_pc')

for i, d in enumerate(dates_raw):
    dailyNewCases = list(list_diff_pc.iloc[i])
    merged[d] = dailyNewCases

# Calculate circle sizes that are proportional to dnc per capita
# Set the latest dnc as default
merged['size'] = merged.iloc[:, -1] * 1e5 / 5 + 10
merged['dnc'] = merged.iloc[:, -2]

# Build a GeoJSONDataSource from merged
geosource = GeoJSONDataSource(geojson=merged.to_json())

# Task 2: Data Visualization

# T2.1 Create linear color mappers for 2 attributes in demo_raw: population density, hospital beds per capita
# Map their maximum values to the high, and mimimum to the low
labels = ['Density', 'BedsPerCapita']

palette = bp.inferno(256)[::-1]

mappers = {}
mappers['Density'] = linear_cmap(field_name='Density',
                                 palette=palette,
                                 low=min(demo_raw.Density),
                                 high=max(demo_raw.Density))
mappers['BedsPerCapita'] = linear_cmap(field_name='BedsPerCapita',
Beispiel #10
0
#mergeset = pd.merge(puds, df_tanggal('07-04-20'), how='inner', left_on= 'name', right_on='Kelurahan')

#print(mergeset[['Kecamatan','Kelurahan', 'Konfirmasi' ,'geometry']])
#mergeset.head()
#mergeset.info()
#print(mergeset[mergeset['is_in_muni']=='Karangpilang'])

#tampilkan peta chloropleth

#ubah GEOjson.
#merged_json = json.loads(mergeset.to_json())
#json_data = json.dumps(merged_json)


#Oper data GEOJson ke parser
geosource = GeoJSONDataSource(geojson = merged_json('07-04-20'))
input_field = 'Konfirmasi'
hover = HoverTool(tooltips = [('Nama Kecamatan','@Kecamatan'),('Nama Kelurahan','@Kelurahan'),('Jumlah Konfirmasi Positif COVID-19','@Konfirmasi')])


p = make_plot(input_field)


# Make a slider object: slider 
select2 = Select(title = 'Tanggal', value = '07-04-20', options=['01-04-20','02-04-20','03-04-20','04-04-20','05-04-20','06-04-20','07-04-20'])
select2.on_change('value', update_plot)

# Make a selection object: select
select = Select(title='Pilih Kriteria:', value='Konfirmasi', options=['ODP', 'PDP','Konfirmasi'])
select.on_change('value', update_plot)
                                 advanced_plotting=True if
                                 ((enable_advancedStats) or
                                  (enable_performanceStats)) else False)
    plt.xaxis.major_tick_line_color = None
    plt.yaxis.major_tick_line_color = None
    plt.xaxis.minor_tick_line_color = None
    plt.yaxis.minor_tick_line_color = None
    plt.xaxis[0].ticker.num_minor_ticks = 0
    plt.yaxis[0].ticker.num_minor_ticks = 0
    plt.yaxis.formatter = NumeralTickFormatter(format='0,0')
    return plt


advanced_mode = True

covid19_geosource = GeoJSONDataSource(geojson=merged_json)
plot_title = None  #'COVID19 outbreak in India'
app_title = 'COVID19 India'

India_totalCases = covid19_data['total_cases'].sum()
India_totalDeaths = covid19_data['deaths'].sum()
print(India_totalCases)

basic_covid19_plot = covid19_plot(covid19_geosource,
                                  input_df=covid19_data,
                                  input_field='total_cases',
                                  color_field='total_cases',
                                  enable_IndiaStats=True,
                                  integer_plot=True,
                                  plot_title=plot_title)
basicPlot_tab = Panel(child=basic_covid19_plot, title="⌂")
Beispiel #12
0

def get_bounds(selectedAgegroups, selectedMeasure):
    df_age = df[df.AGEGROUP.isin(selectedAgegroups)].copy()
    df_age.Infected = df_age[selectedMeasure]
    df_age.Infected_plus = df_age.groupby(['OBJECTID', 'Time'],
                                          sort=False).sum().Infected.repeat(
                                              len(selectedAgegroups)).values
    test = df_age.Infected_plus
    mini = test.min()
    maxi = test.max()
    return mini, maxi


#Input GeoJSON source that contains features for plotting.
geosource = GeoJSONDataSource(
    geojson=json_data(0, ['AGE_0_18'], 'INFECTED_NOSYMPTOMS_NOTCONTAGIOUS'))
a, b = get_bounds(['AGE_0_18'], 'INFECTED_NOSYMPTOMS_NOTCONTAGIOUS')
#Define a color palette.
palette = brewer['YlOrRd'][8]
palette = palette[::-1]
color_mapper = LinearColorMapper(palette=palette,
                                 low=a,
                                 high=b,
                                 nan_color='#d9d9d9')
#tick_labels = {'0': '0', '5': '5', '10':'10', '20':'20', '30':'30','45':'45', '60':'60', '70': '>70'}

# Initialization
AGEGROUPS = df.AGEGROUP.unique()
PERIODS = df.Time.unique()

Beispiel #13
0
d = dict(zip(cities, [{'Longitude': '', 'Latitude': ''} for c in cities]))
for i in range(len(data)):
    if data['City'][i] in cities:
        d[data['City'][i]]['Type'] = data['Type'][i]
        d[data['City'][i]]['University'] = data['University'][i]
        d[data['City'][i]]['Name'] = data['Name'][i]
        d[data['City'][i]]['Sectors'] = data['Sectors'][i]
        d[data['City'][i]]['Link '] = data['Link '][i]
        d[data['City'][i]]['Longitude'] = longDict[data['City'][i]]
        d[data['City'][i]]['Latitude'] = latDict[data['City'][i]]

ndf = pd.DataFrame.from_dict(d).T
ndfna = ndf[ndf['Type'].notna()]

world = gpd.read_file(gpd.datasets.get_path('naturalearth_lowres'))
geosource = GeoJSONDataSource(geojson=world.to_json())

#Définir une palette

#Define a sequential multi-hue color palette.
palette = brewer['YlGnBu'][8]

# Create figure object.
p = figure(title="LEGAL HUB",
           plot_height=700,
           plot_width=1100,
           toolbar_location='below',
           tools='box_zoom, reset, undo, save, pan')
p.xgrid.grid_line_color = None
p.ygrid.grid_line_color = None
# On trace la carte du monde grace a notre objet geosource
Beispiel #14
0
def plot_map(json_data,
             title,
             mapping_field,
             min_value,
             max_value,
             n_colors=6,
             plot_height=600,
             plot_width=950,
             palette_name='RdYlBu',
             reverse_palette=False):
    """
    Creates a country map to display on a notebook with a continuous variable as a color  
    """
    geosource = GeoJSONDataSource(geojson=json_data)

    # Define a sequential multi-hue color palette.
    palette = brewer[palette_name][n_colors]

    # Reverse color order so that dark blue is highest obesity.
    if reverse_palette:
        palette = palette[::-1]

    # Instantiate LinearColorMapper that linearly maps numbers in a range, into a sequence of colors.
    color_mapper = LinearColorMapper(palette=palette,
                                     low=min_value,
                                     high=max_value)

    # Create color bar.
    color_bar = ColorBar(color_mapper=color_mapper,
                         width=500,
                         height=20,
                         border_line_color=None,
                         location=(0, 0),
                         orientation='horizontal')

    # Create figure object.
    p = figure(title=title,
               plot_height=plot_height,
               plot_width=plot_width,
               toolbar_location=None)
    p.xgrid.grid_line_color = None
    p.ygrid.grid_line_color = None

    # Add patch renderer to figure.
    p.patches('xs',
              'ys',
              source=geosource,
              fill_color={
                  'field': mapping_field,
                  'transform': color_mapper
              },
              line_color='black',
              line_width=0.25,
              fill_alpha=1)

    # Specify figure layout.
    p.add_layout(color_bar, 'below')

    # Display figure inline in Jupyter Notebook.
    output_notebook()

    # Display figure.
    return p
Beispiel #15
0
def make_plot(df_covid_election, contiguous_usa):
    '''
    This function makes maps of all states to show 2020 or 2016 election
    results and Covid data together. Users can choose to see which year's
    election result they want to see by clicking on the tabs provided.

    Args:
    - df_covid_election: (csv) Covid and election data in a csv file
    - contiguous_usa: (shp) shape data of the U.S. to make a map

    Returns:
    - plots: contains two plots and tabs on top
    '''
    # Merge shapefile with covid data
    map_info = contiguous_usa.merge(df_covid_election,
                                    left_on="NAME",
                                    right_on="state")
    # Drop Alaska and Hawaii
    map_info = map_info.loc[~map_info['NAME'].isin(['Alaska', 'Hawaii'])]
    # Input GeoJSON source that contains features for plotting
    geosource = GeoJSONDataSource(geojson=map_info.to_json())
    base_colors = [
        "#cb181d", "#fb6a4a", "#fcae91", "#fee5d9", "#eff3ff", "#bdd7e7",
        "#6baed6", "#2171b5"
    ]
    # Instantiate LinearColorMapper that linearly maps numbers in a range,
    # into a sequence of colors.
    low2020 = df_covid_election["color_2020"].min()
    high2020 = df_covid_election["color_2020"].max()
    color_mapper_2020 = LinearColorMapper(palette=base_colors,
                                          low=low2020,
                                          high=high2020)
    low2016 = df_covid_election["color_2016"].min()
    high2016 = df_covid_election["color_2016"].max()
    color_mapper_2016 = LinearColorMapper(palette=base_colors,
                                          low=low2016,
                                          high=high2016)
    tick_labels_2020 = {
        '-8': 'Trump wins',
        '-6': '',
        '-4': '',
        '-2': '',
        '2': '',
        '4': '',
        '6': '',
        '8': 'Biden wins'
    }
    tick_labels_2016 = {
        '-8': 'Trump wins',
        '-6': '',
        '-4': '',
        '-2': '',
        '2': '',
        '4': '',
        '6': '',
        '8': 'Clinton wins'
    }

    # Create color bar.
    color_bar_2020 = ColorBar(color_mapper=color_mapper_2020,
                              label_standoff=10,
                              width=500,
                              height=20,
                              border_line_color=None,
                              location=(0, 0),
                              orientation='horizontal',
                              major_label_overrides=tick_labels_2020)
    color_bar_2016 = ColorBar(color_mapper=color_mapper_2016,
                              label_standoff=10,
                              width=500,
                              height=20,
                              border_line_color=None,
                              location=(0, 0),
                              orientation='horizontal',
                              major_label_overrides=tick_labels_2016)

    # Create figure object
    p2020 = figure(title='COVID-19 cases & 2020 election',
                   plot_height=600,
                   plot_width=950,
                   toolbar_location='below',
                   tools="pan, wheel_zoom, box_zoom, reset")
    p2020.xgrid.grid_line_color = None
    p2020.ygrid.grid_line_color = None
    p2016 = figure(title='COVID-19 cases & 2016 election',
                   plot_height=600,
                   plot_width=950,
                   toolbar_location='below',
                   tools="pan, wheel_zoom, box_zoom, reset")
    p2016.xgrid.grid_line_color = None
    p2016.ygrid.grid_line_color = None

    # Add patch renderer to figure
    states_2020 = p2020.patches('xs',
                                'ys',
                                source=geosource,
                                fill_color={
                                    'field': 'color_2020',
                                    'transform': color_mapper_2020
                                },
                                line_color="gray",
                                line_width=0.25,
                                fill_alpha=1)
    states_2016 = p2016.patches('xs',
                                'ys',
                                source=geosource,
                                fill_color={
                                    'field': 'color_2016',
                                    'transform': color_mapper_2016
                                },
                                line_color="gray",
                                line_width=0.25,
                                fill_alpha=1)
    # Create hover tool
    p2020.add_tools(
        HoverTool(renderers=[states_2020],
                  tooltips=[('State', '@NAME'),
                            ('Case Rate per 100000',
                             '@{Case Rate per 100000}'),
                            ('Confirmed cases', '@{Total Cases}'),
                            ('Total deaths', '@{Total Deaths}')]))
    p2016.add_tools(
        HoverTool(renderers=[states_2016],
                  tooltips=[('State', '@NAME'),
                            ('Case Rate per 100000',
                             '@{Case Rate per 100000}'),
                            ('Confirmed cases', '@{Total Cases}'),
                            ('Total deaths', '@{Total Deaths}')]))
    # Specify layout
    p2020.add_layout(color_bar_2020, 'below')
    p2016.add_layout(color_bar_2016, 'below')
    panel_2020 = Panel(child=p2020, title='COVID-19 cases & 2020 election')
    panel_2016 = Panel(child=p2016, title='COVID-19 cases & 2016 election')
    plots = Tabs(tabs=[panel_2020, panel_2016])
    return plots
Beispiel #16
0
            zipcodes[zipcode]]['properties']['has_data'] = 'NO'

# if closest zip codes are also in geojson file, we can visualize it. We set them to a lighter color "1"
distances = chi_zipcode_to_dist[zipcodes_to_plot]
num_neighbor_count = 0
for neighbor_idx in range(len(distances)):
    if shared_zips[distances[neighbor_idx][0]] == 2:
        num_neighbor_count += 1
        chi_json['features'][zipcodes[distances[neighbor_idx]
                                      [0]]]['properties']['color_type'] = 1
    if num_neighbor_count == num_neighbor:
        break

# convert json to string
geojson = json.dumps(chi_json)
geo_source = GeoJSONDataSource(geojson=geojson)


#
# interactive view of hood2vec.
#
def make_map(zipcodes_to_plot='60608',
             num_neighbor=3,
             period_str='midday',
             cate=[]):
    """
    input: updated parameters selected by users
    output: updated visualization of nearby neighbors
    """
    with open('chi-zip-code-tabulation-areas-2012.geojson', 'rt') as json_file:
        chi_json = json.load(json_file)
Beispiel #17
0
from atlas_db import atlas
import pymongo

from bokeh.io import show, output_notebook
from bokeh.models import (CDSView, ColorBar, ColumnDataSource, CustomJS,
                          CustomJSFilter, GeoJSONDataSource, HoverTool,
                          LinearColorMapper, Slider)
from bokeh.layouts import column, row, widgetbox
from bokeh.palettes import brewer
from bokeh.plotting import figure

print("loading geojson file...")
ny = gpd.read_file("bokehapp/geojson/ny.geojson")
ny = ny.set_index('ZIP_CODE')
ny_source = GeoJSONDataSource(geojson=ny.to_json())
print("finish loading geojson file...")

# Define color palettes
palette = brewer['OrRd'][8]
palette = palette[::
                  -1]  # reverse order of colors so higher values have darker colors
# Instantiate LinearColorMapper that linearly maps numbers in a range, into a sequence of colors.
color_mapper = LinearColorMapper(palette=palette, low=0, high=1)

# Create color bar.
color_bar = ColorBar(color_mapper=color_mapper,
                     label_standoff=8,
                     width=500,
                     height=20,
                     border_line_color=None,
Beispiel #18
0
def geoplot(
    gdf_in,
    geometry_column="geometry",
    figure=None,
    figsize=None,
    title="",
    xlabel="Longitude",
    ylabel="Latitude",
    xlim=None,
    ylim=None,
    color="blue",
    colormap=None,
    colormap_uselog=False,
    colormap_range=None,
    category=None,
    dropdown=None,
    slider=None,
    slider_range=None,
    slider_name="",
    show_colorbar=True,
    colorbar_tick_format=None,
    xrange=None,
    yrange=None,
    hovertool=True,
    hovertool_columns=[],
    hovertool_string=None,
    simplify_shapes=None,
    tile_provider="CARTODBPOSITRON_RETINA",
    tile_provider_url=None,
    tile_attribution="",
    tile_alpha=1,
    panning=True,
    zooming=True,
    toolbar_location="right",
    show_figure=True,
    return_figure=True,
    return_html=False,
    legend=True,
    webgl=True,
    **kwargs,
):
    """Doc-String: TODO"""

    # Imports:
    import bokeh.plotting
    from bokeh.plotting import show
    from bokeh.models import (
        HoverTool,
        LogColorMapper,
        LinearColorMapper,
        GeoJSONDataSource,
        WheelZoomTool,
        ColorBar,
        BasicTicker,
        LogTicker,
        Select,
        Slider,
        ColumnDataSource,
    )
    from bokeh.models.callbacks import CustomJS
    from bokeh.models.widgets import Dropdown
    from bokeh.palettes import all_palettes
    from bokeh.layouts import row, column

    # Make a copy of the input geodataframe:
    gdf = gdf_in.copy()

    # Check layertypes:
    if type(gdf) != pd.DataFrame:
        layertypes = []
        if "Point" in str(gdf.geom_type.unique()):
            layertypes.append("Point")
        if "Line" in str(gdf.geom_type.unique()):
            layertypes.append("Line")
        if "Polygon" in str(gdf.geom_type.unique()):
            layertypes.append("Polygon")
        if len(layertypes) > 1:
            raise Exception(
                f"Can only plot GeoDataFrames/Series with single type of geometry (either Point, Line or Polygon). Provided is a GeoDataFrame/Series with types: {layertypes}"
            )
    else:
        layertypes = ["Point"]

    # Get and check provided parameters for geoplot:
    figure_options = {
        "title": title,
        "x_axis_label": xlabel,
        "y_axis_label": ylabel,
        "plot_width": 600,
        "plot_height": 400,
        "toolbar_location": toolbar_location,
        "active_scroll": "wheel_zoom",
        "x_axis_type": "mercator",
        "y_axis_type": "mercator",
    }
    if not figsize is None:
        width, height = figsize
        figure_options["plot_width"] = width
        figure_options["plot_height"] = height
    if webgl:
        figure_options["output_backend"] = "webgl"

    if type(gdf) != pd.DataFrame:
        # Convert GeoDataFrame to Web Mercator Projection:
        gdf.to_crs(epsg=3857, inplace=True)

        # Simplify shapes if wanted:
        if isinstance(simplify_shapes, numbers.Number):
            if layertypes[0] in ["Line", "Polygon"]:
                gdf[geometry_column] = gdf[geometry_column].simplify(simplify_shapes)
        elif not simplify_shapes is None:
            raise ValueError(
                "<simplify_shapes> parameter only accepts numbers or None."
            )

    # Check for category, dropdown or slider (choropleth map column):
    category_options = 0
    if not category is None:
        category_options += 1
        category_columns = [category]
    if not dropdown is None:
        category_options += 1
        category_columns = dropdown
    if not slider is None:
        category_options += 1
        category_columns = slider
    if category_options > 1:
        raise ValueError(
            "Only one of <category>, <dropdown> or <slider> parameters is allowed to be used at once."
        )

    # Check for category (single choropleth plot):
    if category is None:
        pass
    elif isinstance(category, (list, tuple)):
        raise ValueError(
            "For <category>, please provide an existing single column of the GeoDataFrame."
        )
    elif category in gdf.columns:
        pass
    else:
        raise ValueError(
            f"Could not find column '{category}' in GeoDataFrame. For <category>, please provide an existing single column of the GeoDataFrame."
        )

    # Check for dropdown (multiple choropleth plots via dropdown selection):
    if dropdown is None:
        pass
    elif not isinstance(dropdown, (list, tuple)):
        raise ValueError(
            "For <dropdown>, please provide a list/tuple of existing columns of the GeoDataFrame."
        )
    else:
        for col in dropdown:
            if col not in gdf.columns:
                raise ValueError(
                    f"Could not find column '{col}' for <dropdown> in GeoDataFrame. "
                )

    # Check for slider (multiple choropleth plots via slider selection):
    if slider is None:
        pass
    elif not isinstance(slider, (list, tuple)):
        raise ValueError(
            "For <slider>, please provide a list/tuple of existing columns of the GeoDataFrame."
        )
    else:
        for col in slider:
            if col not in gdf.columns:
                raise ValueError(
                    f"Could not find column '{col}' for <slider> in GeoDataFrame. "
                )

        if not slider_range is None:
            if not isinstance(slider_range, Iterable):
                raise ValueError(
                    "<slider_range> has to be a type that is iterable like list, tuple, range, ..."
                )
            else:
                slider_range = list(slider_range)
                if len(slider_range) != len(slider):
                    raise ValueError(
                        "The number of elements in <slider_range> has to be the same as in <slider>."
                    )
                steps = []
                for i in range(len(slider_range) - 1):
                    steps.append(slider_range[i + 1] - slider_range[i])

                if len(set(steps)) > 1:
                    raise ValueError(
                        "<slider_range> has to have equal step size between each elements (like a range-object)."
                    )
                else:
                    slider_step = steps[0]
                    slider_start = slider_range[0]
                    slider_end = slider_range[-1]

    # Check colormap if either <category>, <dropdown> or <slider> is choosen:
    if category_options == 1:
        if colormap is None:
            colormap = blue_colormap
        elif isinstance(colormap, (tuple, list)):
            if len(colormap) > 1:
                pass
            else:
                raise ValueError(
                    f"<colormap> only accepts a list/tuple of at least two colors or the name of one of the following predefined colormaps (see also https://bokeh.pydata.org/en/latest/docs/reference/palettes.html ): {list(all_palettes.keys())}"
                )
        elif isinstance(colormap, str):
            if colormap in all_palettes:
                colormap = all_palettes[colormap]
                colormap = colormap[max(colormap.keys())]
            else:
                raise ValueError(
                    f"Could not find <colormap> with name {colormap}. The following predefined colormaps are supported (see also https://bokeh.pydata.org/en/latest/docs/reference/palettes.html ): {list(all_palettes.keys())}"
                )
        else:
            raise ValueError(
                f"<colormap> only accepts a list/tuple of at least two colors or the name of one of the following predefined colormaps (see also https://bokeh.pydata.org/en/latest/docs/reference/palettes.html ): {list(all_palettes.keys())}"
            )
    else:
        if isinstance(color, str):
            colormap = [color]
        elif color is None:
            colormap = ["blue"]
        else:
            raise ValueError(
                "<color> has to be a string specifying the fill_color of the map glyph."
            )

    # Check xlim & ylim:
    if xlim is not None:
        if isinstance(xlim, (tuple, list)):
            if len(xlim) == 2:
                xmin, xmax = xlim
                for _ in [xmin, xmax]:
                    if not -180 < _ <= 180:
                        raise ValueError(
                            "Limits for x-axis (=Longitude) have to be between -180 and 180."
                        )
                if not xmin < xmax:
                    raise ValueError("xmin has to be smaller than xmax.")

                from pyproj import Transformer

                transformer = Transformer.from_crs("epsg:4326", "epsg:3857")
                xmin = transformer.transform(0, xmin)[0]
                xmax = transformer.transform(0, xmax)[0]
                figure_options["x_range"] = (xmin, xmax)
            else:
                raise ValueError(
                    "Limits for x-axis (=Longitude) have to be of form [xmin, xmax] with values between -180 and 180."
                )
        else:
            raise ValueError(
                "Limits for x-axis (=Longitude) have to be of form [xmin, xmax] with values between -180 and 180."
            )
    if ylim is not None:
        if isinstance(ylim, (tuple, list)):
            if len(ylim) == 2:
                ymin, ymax = ylim
                for _ in [ymin, ymax]:
                    if not -90 < _ <= 90:
                        raise ValueError(
                            "Limits for y-axis (=Latitude) have to be between -90 and 90."
                        )
                if not ymin < ymax:
                    raise ValueError("ymin has to be smaller than ymax.")

                from pyproj import Transformer

                transformer = Transformer.from_crs("epsg:4326", "epsg:3857")
                ymin = transformer.transform(ymin, 0)[1]
                ymax = transformer.transform(ymax, 0)[1]
                figure_options["y_range"] = (ymin, ymax)
            else:
                raise ValueError(
                    "Limits for y-axis (=Latitude) have to be of form [ymin, ymax] with values between -90 and 90."
                )
        else:
            raise ValueError(
                "Limits for y-axis (=Latitude) have to be of form [ymin, ymax] with values between -90 and 90."
            )

    # Create Figure to draw:
    old_layout = None
    if figure is None:
        p = bokeh.plotting.figure(**figure_options)

        # Add Tile Source as Background:
        p = _add_backgroundtile(
            p, tile_provider, tile_provider_url, tile_attribution, tile_alpha
        )

    elif isinstance(figure, type(bokeh.plotting.figure())):
        p = figure
    elif isinstance(figure, type(column())):
        old_layout = figure
        p = _get_figure(old_layout)
    else:
        raise ValueError(
            "Parameter <figure> has to be of type bokeh.plotting.figure or bokeh.layouts.column."
        )

    # Get ridd of zoom on axes:
    for t in p.tools:
        if type(t) == WheelZoomTool:
            t.zoom_on_axis = False

    # Hide legend if wanted:
    legend_input = legend
    if isinstance(legend, str):
        pass
    else:
        legend = "GeoLayer"

    # Define colormapper:
    if len(colormap) == 1:
        kwargs["fill_color"] = colormap[0]

    elif not category is None:
        # Check if category column is numerical:
        if not issubclass(gdf[category].dtype.type, np.number):
            raise NotImplementedError(
                f"<category> plot only yet implemented for numerical columns. Column '{category}' is not numerical."
            )

        field = category
        colormapper_options = {"palette": colormap}
        if not colormap_range is None:
            if not isinstance(colormap_range, (tuple, list)):
                raise ValueError(
                    "<colormap_range> can only be 'None' or a tuple/list of form (min, max)."
                )
            elif len(colormap_range) == 2:
                colormapper_options["low"] = colormap_range[0]
                colormapper_options["high"] = colormap_range[1]
        else:
            colormapper_options["low"] = gdf[field].min()
            colormapper_options["high"] = gdf[field].max()
        if colormap_uselog:
            colormapper = LogColorMapper(**colormapper_options)
        else:
            colormapper = LinearColorMapper(**colormapper_options)
        kwargs["fill_color"] = {"field": "Colormap", "transform": colormapper}
        if not isinstance(legend, str):
            legend = str(field)

    elif not dropdown is None:
        # Check if all columns in dropdown selection are numerical:
        for col in dropdown:
            if not issubclass(gdf[col].dtype.type, np.number):
                raise NotImplementedError(
                    f"<dropdown> plot only yet implemented for numerical columns. Column '{col}' is not numerical."
                )

        field = dropdown[0]
        colormapper_options = {"palette": colormap}
        if not colormap_range is None:
            if not isinstance(colormap_range, (tuple, list)):
                raise ValueError(
                    "<colormap_range> can only be 'None' or a tuple/list of form (min, max)."
                )
            elif len(colormap_range) == 2:
                colormapper_options["low"] = colormap_range[0]
                colormapper_options["high"] = colormap_range[1]
        else:
            colormapper_options["low"] = gdf[dropdown].min().min()
            colormapper_options["high"] = gdf[dropdown].max().max()
        if colormap_uselog:
            colormapper = LogColorMapper(**colormapper_options)
        else:
            colormapper = LinearColorMapper(**colormapper_options)
        kwargs["fill_color"] = {"field": "Colormap", "transform": colormapper}
        legend = " " + field

    elif not slider is None:
        # Check if all columns in dropdown selection are numerical:
        for col in slider:
            if not issubclass(gdf[col].dtype.type, np.number):
                raise NotImplementedError(
                    f"<slider> plot only yet implemented for numerical columns. Column '{col}' is not numerical."
                )

        field = slider[0]
        colormapper_options = {"palette": colormap}
        if not colormap_range is None:
            if not isinstance(colormap_range, (tuple, list)):
                raise ValueError(
                    "<colormap_range> can only be 'None' or a tuple/list of form (min, max)."
                )
            elif len(colormap_range) == 2:
                colormapper_options["low"] = colormap_range[0]
                colormapper_options["high"] = colormap_range[1]
        else:
            colormapper_options["low"] = gdf[slider].min().min()
            colormapper_options["high"] = gdf[slider].max().max()
        if colormap_uselog:
            colormapper = LogColorMapper(**colormapper_options)
        else:
            colormapper = LinearColorMapper(**colormapper_options)
        kwargs["fill_color"] = {"field": "Colormap", "transform": colormapper}
        if not isinstance(legend, str):
            legend = "Geolayer"

    # Check that only hovertool_columns or hovertool_string is used:
    if isinstance(hovertool_columns, (list, tuple, str)):
        if len(hovertool_columns) > 0 and hovertool_string is not None:
            raise ValueError(
                "Either <hovertool_columns> or <hovertool_string> can be used, but not both at the same time."
            )
    else:
        raise ValueError(
            "<hovertool_columns> has to be a list of columns of the GeoDataFrame or the string 'all'."
        )

    if hovertool_string is not None:
        hovertool_columns = "all"

    # Check for Hovertool columns:
    if hovertool:
        if not isinstance(hovertool_columns, (list, tuple)):
            if hovertool_columns == "all":
                hovertool_columns = list(
                    filter(lambda col: col != geometry_column, gdf.columns)
                )
            else:
                raise ValueError(
                    "<hovertool_columns> has to be a list of columns of the GeoDataFrame or the string 'all'."
                )
        elif len(hovertool_columns) == 0:
            if not category is None:
                hovertool_columns = [category]
            elif not dropdown is None:
                hovertool_columns = dropdown
            elif not slider is None:
                hovertool_columns = slider
            else:
                hovertool_columns = []
        else:
            for col in hovertool_columns:
                if col not in gdf.columns:
                    raise ValueError(
                        f"Could not find columns '{col}' in GeoDataFrame. <hovertool_columns> has to be a list of columns of the GeoDataFrame or the string 'all'."
                    )
    else:
        if category is None:
            hovertool_columns = []
        else:
            hovertool_columns = [category]

    # Reduce DataFrame to needed columns:
    if type(gdf) == pd.DataFrame:
        gdf["Geometry"] = 0
        additional_columns = ["x", "y"]
    else:
        additional_columns = [geometry_column]
    for kwarg, value in kwargs.items():
        if isinstance(value, Hashable):
            if value in gdf.columns:
                additional_columns.append(value)
    if category_options == 0:
        gdf = gdf[list(set(hovertool_columns) | set(additional_columns))]
    else:
        gdf = gdf[
            list(
                set(hovertool_columns) | set(category_columns) | set(additional_columns)
            )
        ]
        gdf["Colormap"] = gdf[field]
        field = "Colormap"

    # Create GeoJSON DataSource for Plot:
    if type(gdf) != pd.DataFrame:
        geo_source = GeoJSONDataSource(geojson=gdf.to_json())
    else:
        geo_source = gdf

    # Draw Glyph on Figure:
    layout = None
    if "Point" in layertypes:
        if "line_color" not in kwargs:
            kwargs["line_color"] = kwargs["fill_color"]
        glyph = p.scatter(
            x="x", y="y", source=geo_source, legend_label=legend, **kwargs
        )

    if "Line" in layertypes:
        if "line_color" not in kwargs:
            kwargs["line_color"] = kwargs["fill_color"]
            del kwargs["fill_color"]
        glyph = p.multi_line(
            xs="xs", ys="ys", source=geo_source, legend_label=legend, **kwargs
        )

    if "Polygon" in layertypes:

        if "line_color" not in kwargs:
            kwargs["line_color"] = "black"

        # Creates from a geoDataFrame with Polygons and Multipolygons a Pandas DataFrame
        # with x any y columns specifying the geometry of the Polygons:
        geo_source = ColumnDataSource(
            convert_geoDataFrame_to_patches(gdf, geometry_column)
        )

        # Plot polygons:
        glyph = p.multi_polygons(
            xs="__x__", ys="__y__", source=geo_source, legend_label=legend, **kwargs
        )

    # Add hovertool:
    if hovertool and (category_options == 1 or len(hovertool_columns) > 0):
        my_hover = HoverTool(renderers=[glyph])
        if hovertool_string is None:
            my_hover.tooltips = [(str(col), "@{%s}" % col) for col in hovertool_columns]
        else:
            my_hover.tooltips = hovertool_string
        p.add_tools(my_hover)

    # Add colorbar:
    if show_colorbar and category_options == 1:
        colorbar_options = {
            "color_mapper": colormapper,
            "label_standoff": 12,
            "border_line_color": None,
            "location": (0, 0),
        }
        if colormap_uselog:
            colorbar_options["ticker"] = LogTicker()

        if colorbar_tick_format:
            colorbar_options["formatter"] = get_tick_formatter(colorbar_tick_format)

        colorbar = ColorBar(**colorbar_options)

        p.add_layout(colorbar, "right")

    # Add Dropdown Widget:
    if not dropdown is None:
        # Define Dropdown widget:
        dropdown_widget = Select(
            title="Select Choropleth Layer", options=list(zip(dropdown, dropdown))
        )

        # Define Callback for Dropdown widget:
        callback = CustomJS(
            args=dict(
                dropdown_widget=dropdown_widget,
                geo_source=geo_source,
                legend=p.legend[0].items[0],
            ),
            code="""

                //Change selection of field for Colormapper for choropleth plot:
                geo_source.data["Colormap"] = geo_source.data[dropdown_widget.value];
                geo_source.change.emit();

                //Change label of Legend:
                legend.label["value"] = " " + dropdown_widget.value;

                            """,
        )
        dropdown_widget.js_on_change("value", callback)

        # Add Dropdown widget above the plot:
        if old_layout is None:
            layout = column(dropdown_widget, p)
        else:
            layout = column(dropdown_widget, old_layout)

    # Add Slider Widget:
    if not slider is None:

        if slider_range is None:
            slider_start = 0
            slider_end = len(slider) - 1
            slider_step = 1

        value2name = ColumnDataSource(
            {
                "Values": np.arange(
                    slider_start, slider_end + slider_step, slider_step
                ),
                "Names": slider,
            }
        )

        # Define Slider widget:
        slider_widget = Slider(
            start=slider_start,
            end=slider_end,
            value=slider_start,
            step=slider_step,
            title=slider_name,
        )

        # Define Callback for Slider widget:
        callback = CustomJS(
            args=dict(
                slider_widget=slider_widget,
                geo_source=geo_source,
                value2name=value2name,
            ),
            code="""

                //Change selection of field for Colormapper for choropleth plot:
                var slider_value = slider_widget.value;
                var i;
                for(i=0; i<value2name.data["Names"].length; i++)
                    {
                    if (value2name.data["Values"][i] == slider_value)
                        {
                         var name = value2name.data["Names"][i];
                         }

                    }
                geo_source.data["Colormap"] = geo_source.data[name];
                geo_source.change.emit();

                            """,
        )
        slider_widget.js_on_change("value", callback)

        # Add Slider widget above the plot:
        if old_layout is None:
            layout = column(slider_widget, p)
        else:
            layout = column(slider_widget, old_layout)

    # Hide legend if user wants:
    if legend_input is False:
        p.legend.visible = False

    # Set click policy for legend:
    p.legend.click_policy = "hide"

    # Set panning option:
    if panning is False:
        p.toolbar.active_drag = None

    # Set zooming option:
    if zooming is False:
        p.toolbar.active_scroll = None

    # Display plot and if wanted return plot:
    if layout is None:
        if old_layout is None:
            layout = p
        else:
            layout = old_layout

    # Display plot if wanted
    if show_figure:
        show(layout)

    # Return as (embeddable) HTML if wanted:
    if return_html:
        return embedded_html(layout)

    # Return plot:
    if return_figure:
        return layout
Beispiel #19
0
"""
Hayden Le's GeoDev Technical Assessment Submission
"""

import pandas as pd
from shapely.geometry import Point

from bokeh.models import GeoJSONDataSource, LinearColorMapper, HoverTool

import geopandas as gpd
from bokeh.palettes import BuPu3 as palette
from bokeh.plotting import figure, save

# --- country borders
world = gpd.read_file(gpd.datasets.get_path('naturalearth_lowres'))
geo_source = GeoJSONDataSource(geojson=world.to_json())

# --- project locations
projects = pd.read_table('locations.tsv', sep='\t')
geometry = [Point(xy) for xy in zip(projects.longitude, projects.latitude)]
crs = world.crs
projects_df = gpd.GeoDataFrame(projects, crs=crs, geometry=geometry)
project_source = GeoJSONDataSource(geojson=projects_df.to_json())

# --- create plot/figure
p = figure(title="Project Locations",
           plot_width=800,
           plot_height=500,
           x_range=(0, 100),
           y_range=(30, 85),
           toolbar_location="below")
Beispiel #20
0
def geoplot(gdf_in,
            fig=None,
            figsize=None,
            title="",
            xlabel="Longitude",
            ylabel="Latitude",
            color="blue",
            colormap=None,
            colormap_uselog=False,
            colormap_range=None,
            category=None,
            dropdown=None,
            slider=None,
            slider_range=None,
            slider_name="",
            show_colorbar=True,
            xrange=None,
            yrange=None,
            hovertool=True,
            hovertool_columns=[],
            simplify_shapes=None,
            tile_provider="CARTODBPOSITRON_RETINA",
            tile_provider_url=None,
            tile_attribution="",
            tile_alpha=1,
            toolbar_location="right",
            show_figure=True,
            return_figure=True,
            return_html=False,
            legend=True,
            webgl=True,
            **kwargs):
    """Doc-String: TODO"""

    gdf = gdf_in.copy()

    # Check layertypes:
    layertypes = []
    if "Point" in str(gdf.geom_type.unique()):
        layertypes.append("Point")
    if "Line" in str(gdf.geom_type.unique()):
        layertypes.append("Line")
    if "Polygon" in str(gdf.geom_type.unique()):
        layertypes.append("Polygon")
    if len(layertypes) > 1:
        raise Exception(
            "Can only plot GeoDataFrames/Series with single type of geometry (either Point, Line or Polygon). Provided is a GeoDataFrame/Series with types: %s"
            % layertypes)

    # Get and check provided parameters for geoplot:
    figure_options = {
        "title": title,
        "x_axis_label": xlabel,
        "y_axis_label": ylabel,
        "plot_width": 600,
        "plot_height": 400,
        "toolbar_location": toolbar_location,
        "active_scroll": "wheel_zoom",
    }
    if not figsize is None:
        width, height = figsize
        figure_options["plot_width"] = width
        figure_options["plot_height"] = height
    if webgl:
        figure_options["output_backend"] = "webgl"

    if not fig is None:
        raise NotImplementedError("Parameter <figure> not yet implemented.")

    # Convert GeoDataFrame to Web Mercador Projection:
    gdf.to_crs({"init": "epsg:3857"}, inplace=True)

    # Simplify shapes if wanted:
    if isinstance(simplify_shapes, numbers.Number):
        if layertypes[0] in ["Line", "Polygon"]:
            gdf["geometry"] = gdf["geometry"].simplify(simplify_shapes)
    elif not simplify_shapes is None:
        raise ValueError(
            "<simplify_shapes> parameter only accepts numbers or None.")

    # Check for category, dropdown or slider (choropleth map column):
    category_options = 0
    if not category is None:
        category_options += 1
        category_columns = [category]
    if not dropdown is None:
        category_options += 1
        category_columns = dropdown
    if not slider is None:
        category_options += 1
        category_columns = slider
    if category_options > 1:
        raise ValueError(
            "Only one of <category>, <dropdown> or <slider> parameters is allowed to be used at once."
        )

    # Check for category (single choropleth plot):
    if category is None:
        pass
    elif isinstance(category, (list, tuple)):
        raise ValueError(
            "For <category>, please provide an existing single column of the GeoDataFrame."
        )
    elif category in gdf.columns:
        pass
    else:
        raise ValueError(
            "Could not find column '%s' in GeoDataFrame. For <category>, please provide an existing single column of the GeoDataFrame."
            % category)

    # Check for dropdown (multiple choropleth plots via dropdown selection):
    if dropdown is None:
        pass
    elif not isinstance(dropdown, (list, tuple)):
        raise ValueError(
            "For <dropdown>, please provide a list/tuple of existing columns of the GeoDataFrame."
        )
    else:
        for col in dropdown:
            if col not in gdf.columns:
                raise ValueError(
                    "Could not find column '%s' for <dropdown> in GeoDataFrame. "
                    % col)

    # Check for slider (multiple choropleth plots via slider selection):
    if slider is None:
        pass
    elif not isinstance(slider, (list, tuple)):
        raise ValueError(
            "For <slider>, please provide a list/tuple of existing columns of the GeoDataFrame."
        )
    else:
        for col in slider:
            if col not in gdf.columns:
                raise ValueError(
                    "Could not find column '%s' for <slider> in GeoDataFrame. "
                    % col)

        if not slider_range is None:
            if not isinstance(slider_range, Iterable):
                raise ValueError(
                    "<slider_range> has to be a type that is iterable like list, tuple, range, ..."
                )
            else:
                slider_range = list(slider_range)
                if len(slider_range) != len(slider):
                    raise ValueError(
                        "The number of elements in <slider_range> has to be the same as in <slider>."
                    )
                steps = []
                for i in range(len(slider_range) - 1):
                    steps.append(slider_range[i + 1] - slider_range[i])

                if len(set(steps)) > 1:
                    raise ValueError(
                        "<slider_range> has to have equal step size between each elements (like a range-object)."
                    )
                else:
                    slider_step = steps[0]
                    slider_start = slider_range[0]
                    slider_end = slider_range[-1]

    # Check colormap if either <category>, <dropdown> or <slider> is choosen:
    if category_options == 1:
        if colormap is None:
            colormap = blue_colormap
        elif isinstance(colormap, (tuple, list)):
            if len(colormap) > 1:
                pass
            else:
                raise ValueError(
                    "<colormap> only accepts a list/tuple of at least two colors or the name of one of the following predefined colormaps (see also https://bokeh.pydata.org/en/latest/docs/reference/palettes.html ): %s"
                    % (list(all_palettes.keys())))
        elif isinstance(colormap, str):
            if colormap in all_palettes:
                colormap = all_palettes[colormap]
                colormap = colormap[max(colormap.keys())]
            else:
                raise ValueError(
                    "Could not find <colormap> with name %s. The following predefined colormaps are supported (see also https://bokeh.pydata.org/en/latest/docs/reference/palettes.html ): %s"
                    % (colormap, list(all_palettes.keys())))
        else:
            raise ValueError(
                "<colormap> only accepts a list/tuple of at least two colors or the name of one of the following predefined colormaps (see also https://bokeh.pydata.org/en/latest/docs/reference/palettes.html ): %s"
                % (list(all_palettes.keys())))
    else:
        if isinstance(color, str):
            colormap = [color]
        else:
            raise ValueError(
                "<color> has to be a string specifying the fill_color of the map glyph."
            )

    # Create Figure to draw:
    p = figure(x_axis_type="mercator",
               y_axis_type="mercator",
               **figure_options)

    # Get ridd of zoom on axes:
    for t in p.tools:
        if type(t) == WheelZoomTool:
            t.zoom_on_axis = False

    # Add Tile Source as Background:
    p = _add_backgroundtile(p, tile_provider, tile_provider_url,
                            tile_attribution, tile_alpha)

    # Hide legend if wanted:
    if not legend:
        p.legend.visible = False
    elif isinstance(legend, str):
        pass
    else:
        legend = "GeoLayer"

    # Define colormapper:
    if len(colormap) == 1:
        kwargs["fill_color"] = colormap[0]

    elif not category is None:
        # Check if category column is numerical:
        if not issubclass(gdf[category].dtype.type, np.number):
            raise NotImplementedError(
                "<category> plot only yet implemented for numerical columns. Column '%s' is not numerical."
                % category)

        field = category
        colormapper_options = {"palette": colormap}
        if not colormap_range is None:
            if not isinstance(colormap_range, (tuple, list)):
                raise ValueError(
                    "<colormap_range> can only be 'None' or a tuple/list of form (min, max)."
                )
            elif len(colormap_range) == 2:
                colormapper_options["low"] = colormap_range[0]
                colormapper_options["high"] = colormap_range[1]
        else:
            colormapper_options["low"] = gdf[field].min()
            colormapper_options["high"] = gdf[field].max()
        if colormap_uselog:
            colormapper = LogColorMapper(**colormapper_options)
        else:
            colormapper = LinearColorMapper(**colormapper_options)
        kwargs["fill_color"] = {"field": "Colormap", "transform": colormapper}
        if not isinstance(legend, str):
            legend = str(field)

    elif not dropdown is None:
        # Check if all columns in dropdown selection are numerical:
        for col in dropdown:
            if not issubclass(gdf[col].dtype.type, np.number):
                raise NotImplementedError(
                    "<dropdown> plot only yet implemented for numerical columns. Column '%s' is not numerical."
                    % col)

        field = dropdown[0]
        colormapper_options = {"palette": colormap}
        if not colormap_range is None:
            if not isinstance(colormap_range, (tuple, list)):
                raise ValueError(
                    "<colormap_range> can only be 'None' or a tuple/list of form (min, max)."
                )
            elif len(colormap_range) == 2:
                colormapper_options["low"] = colormap_range[0]
                colormapper_options["high"] = colormap_range[1]
        else:
            colormapper_options["low"] = gdf[dropdown].min().min()
            colormapper_options["high"] = gdf[dropdown].max().max()
        if colormap_uselog:
            colormapper = LogColorMapper(**colormapper_options)
        else:
            colormapper = LinearColorMapper(**colormapper_options)
        kwargs["fill_color"] = {"field": "Colormap", "transform": colormapper}
        if not isinstance(legend, str):
            legend = "Geolayer"

    elif not slider is None:
        # Check if all columns in dropdown selection are numerical:
        for col in slider:
            if not issubclass(gdf[col].dtype.type, np.number):
                raise NotImplementedError(
                    "<slider> plot only yet implemented for numerical columns. Column '%s' is not numerical."
                    % col)

        field = slider[0]
        colormapper_options = {"palette": colormap}
        if not colormap_range is None:
            if not isinstance(colormap_range, (tuple, list)):
                raise ValueError(
                    "<colormap_range> can only be 'None' or a tuple/list of form (min, max)."
                )
            elif len(colormap_range) == 2:
                colormapper_options["low"] = colormap_range[0]
                colormapper_options["high"] = colormap_range[1]
        else:
            colormapper_options["low"] = gdf[slider].min().min()
            colormapper_options["high"] = gdf[slider].max().max()
        if colormap_uselog:
            colormapper = LogColorMapper(**colormapper_options)
        else:
            colormapper = LinearColorMapper(**colormapper_options)
        kwargs["fill_color"] = {"field": "Colormap", "transform": colormapper}
        if not isinstance(legend, str):
            legend = "Geolayer"

    # Check for Hovertool columns:
    if hovertool:
        if not isinstance(hovertool_columns, (list, tuple)):
            if hovertool_columns == "all":
                hovertool_columns = list(
                    filter(lambda col: col != "geometry", df_shapes.columns))
            else:
                raise ValueError(
                    "<hovertool_columns> has to be a list of columns of the GeoDataFrame or the string 'all'."
                )
        elif len(hovertool_columns) == 0:
            if not category is None:
                hovertool_columns = [category]
            elif not dropdown is None:
                hovertool_columns = dropdown
            elif not slider is None:
                hovertool_columns = slider
            else:
                hovertool_columns = []
        else:
            for col in hovertool_columns:
                if col not in gdf.columns:
                    raise ValueError(
                        "Could not find columns '%s' in GeoDataFrame. <hovertool_columns> has to be a list of columns of the GeoDataFrame or the string 'all'."
                        % col)
    else:
        if category is None:
            hovertool_columns = []
        else:
            hovertool_columns = [category]

    # Reduce DataFrame to needed columns:
    additional_columns = []
    for kwarg, value in kwargs.items():
        if isinstance(value, Hashable):
            if value in gdf.columns:
                additional_columns.append(value)
    if category_options == 0:
        gdf = gdf[list(set(hovertool_columns) | set(additional_columns)) +
                  ["geometry"]]
    else:
        gdf = gdf[list(
            set(hovertool_columns) | set(category_columns)
            | set(additional_columns)) + ["geometry"]]
        gdf["Colormap"] = gdf[field]
        field = "Colormap"

    # Create GeoJSON DataSource for Plot:
    geo_source = GeoJSONDataSource(geojson=gdf.to_json())

    # Draw Glyph on Figure:
    layout = None
    if "Point" in layertypes:
        if "line_color" not in kwargs:
            kwargs["line_color"] = kwargs["fill_color"]
        p.scatter(x="x", y="y", source=geo_source, legend=legend, **kwargs)

    if "Line" in layertypes:
        if "line_color" not in kwargs:
            kwargs["line_color"] = kwargs["fill_color"]
            del kwargs["fill_color"]
        p.multi_line(xs="xs",
                     ys="ys",
                     source=geo_source,
                     legend=legend,
                     **kwargs)

    if "Polygon" in layertypes:

        if "line_color" not in kwargs:
            kwargs["line_color"] = "black"

        # Plot polygons:
        p.patches(xs="xs", ys="ys", source=geo_source, legend=legend, **kwargs)

    if hovertool and (category_options == 1 or len(hovertool_columns) > 0):
        my_hover = HoverTool()
        my_hover.tooltips = [(str(col), "@{%s}" % col)
                             for col in hovertool_columns]
        p.add_tools(my_hover)

    if show_colorbar and category_options == 1:
        colorbar_options = {
            "color_mapper": colormapper,
            "label_standoff": 12,
            "border_line_color": None,
            "location": (0, 0),
        }
        if colormap_uselog:
            colorbar_options["ticker"] = LogTicker()

        colorbar = ColorBar(**colorbar_options)

        p.add_layout(colorbar, "right")

    if not dropdown is None:
        # Define Dropdown widget:
        dropdown_widget = Dropdown(label="Select Choropleth Layer",
                                   menu=list(zip(dropdown, dropdown)))

        # Define Callback for Dropdown widget:
        callback = CustomJS(
            args=dict(dropdown_widget=dropdown_widget,
                      geo_source=geo_source,
                      p=p),
            code="""

                //Change selection of field for Colormapper for choropleth plot:
                geo_source.data["Colormap"] = geo_source.data[dropdown_widget.value];
                geo_source.change.emit();
                //p.legend[0].items[0]["label"] = dropdown_widget.value;

                            """,
        )
        dropdown_widget.js_on_change("value", callback)

        # Add Dropdown widget above the plot:
        layout = column(dropdown_widget, p)

    if not slider is None:

        if slider_range is None:
            slider_start = 0
            slider_end = len(slider) - 1
            slider_step = 1

        value2name = ColumnDataSource({
            "Values":
            np.arange(slider_start, slider_end + slider_step, slider_step),
            "Names":
            slider,
        })

        # Define Slider widget:
        slider_widget = Slider(
            start=slider_start,
            end=slider_end,
            value=slider_start,
            step=slider_step,
            title=slider_name,
        )

        # Define Callback for Slider widget:
        callback = CustomJS(
            args=dict(
                slider_widget=slider_widget,
                geo_source=geo_source,
                value2name=value2name,
            ),
            code="""

                //Change selection of field for Colormapper for choropleth plot:
                var slider_value = slider_widget.value;
                for(i=0; i<value2name.data["Names"].length; i++)
                    {
                    if (value2name.data["Values"][i] == slider_value)
                        {
                         var name = value2name.data["Names"][i];
                         }

                    }
                geo_source.data["Colormap"] = geo_source.data[name];
                geo_source.change.emit();

                            """,
        )
        slider_widget.js_on_change("value", callback)

        # Add Slider widget above the plot:
        layout = column(slider_widget, p)

    # Set click policy for legend:
    p.legend.click_policy = "hide"

    # Display plot and if wanted return plot:
    if layout is None:
        layout = p

    # Display plot if wanted
    if show_figure:
        show(layout)

    # Return as (embeddable) HTML if wanted:
    if return_html:
        return embedded_html(layout)

    # Return plot:
    if return_figure:
        return layout
Beispiel #21
0
def get_geodatasource(pop_states):
    """Get getjsondatasource from geopandas object"""
    json_data = json.dumps(json.loads(pop_states.to_json()))
    return GeoJSONDataSource(geojson=json_data)
Beispiel #22
0
    ]


normalizedTotalCases()
normalizedTotalDeaths()
normalizedTotalCasesPerMillion()
normalizedTotalDeathsPerMillion()

geoDataFrame = geoDataFrame.merge(covidDataFrame,
                                  left_on='country_code',
                                  right_on='iso_code',
                                  how='left')
# convert date column to string as datetime dtype cannot be converted as JSON
geoDataFrame['date'] = geoDataFrame['date'].astype(str)
jsonGeoData = json.loads(geoDataFrame.to_json())
source = GeoJSONDataSource(geojson=json.dumps(jsonGeoData))

# sequential multi-hue color palette.
palette = brewer['YlGnBu'][8]
# reverse color order so that dark blue is highest obesity.
palette = palette[::-1]
color_mapper = LinearColorMapper(palette=palette, low=0, high=8)
# define custom tick labels for color bar.
# tick_labels = {'0': '0%', '5': '5%', '10': '10%', '15': '15%',
#                '20': '20%', '25': '25%', '30': '30%', '35': '35%', '40': '>40%'}
# Create color bar.
color_bar = ColorBar(color_mapper=color_mapper,
                     label_standoff=8,
                     width=500,
                     height=20,
                     border_line_color=None,
Beispiel #23
0
def get_plot(query, conn, desc, first, last):
    # Get one of the results tables
    df = gpd.GeoDataFrame.from_postgis(query,
                                       conn,
                                       geom_col='geom',
                                       crs=from_epsg(3067)).to_crs("EPSG:3857")
    # A point source for labels. df.set_geometry() fails, but this works!
    df_centroids = gpd.GeoDataFrame.from_postgis(
        query, conn, geom_col='geom_centroid',
        crs=from_epsg(3067)).to_crs("EPSG:3857")

    # Classify data (manual classes based on outputs of previous runs!)
    breaks = [-10.1, 10, 101]
    classifier = mc.UserDefined.make(bins=breaks)
    classes = df[['RFChange']].apply(classifier)
    classes.columns = ['Class']
    df = df.join(classes)

    # Collect some statistics:
    # For practical help how to do this in Python:
    # https://pythonfordatascience.org/independent-t-test-python/
    statistics = {
        'min_rfchg': df['RFChange'].min(),
        'max_rfchg': df['RFChange'].max(),
        'min_abschg': df['AbsChange'].min(),
        'max_abschg': df['AbsChange'].max(),
        'mean_rfchg': df['RFChange'].mean(),
        'mean_abschg': df['AbsChange'].mean(),
        'median_abschg': df['AbsChange'].median(),
        'stdev_abschg': df['AbsChange'].std(),
        'mean_T1': df['T1'].mean(),
        'mean_T2': df['T2'].mean(),
        'stdev_T1': df['T1'].std(),
        'stdev_T2': df['T2'].std(),
        'levenestat_abschg': None,
        'levenepval_abschg': None,
        'shapirostat_abschg': None,
        'shapiropval_abschg': None,
        't-stat_abschg': None,
        't-pval_abschg': None,
        't-df_abschg': None
    }
    # None of this makes sense unless both variables have data:
    reshist = None
    resqq = None
    if not ((df['T1'] == 0).all() or (df['T2'] == 0).all()):
        # Null hypothesis for Levene test: both inputs have equal variances.
        statistics['levenestat_abschg'], \
            statistics['levenepval_abschg'] = stats.levene(df['T1'], df['T2'])
        # Null hypothesis for Shapiro-Wilk: normal distribution of residuals.
        diff = df['T2'] - df['T1']
        statistics['shapirostat_abschg'], \
            statistics['shapiropval_abschg'] = stats.shapiro(diff)
        plot_title = 'Residuals for ' + desc + ', ' + first + '–' + last
        reshist = diff.plot(kind='hist',
                            title="\n".join(wrap(plot_title, 60)),
                            figure=plt.figure())
        plt.figure()
        stats.probplot(diff, plot=plt)
        plt.title("\n".join(wrap(plot_title, 60)))
        resqq = plt.gca()
        statistics['t-stat_abschg'], \
            statistics['t-pval_abschg'] = stats.ttest_ind(df['T1'], df['T2'])
        statistics['t-df_abschg'] = df['T1'].count() + df['T2'].count() - 2
        # Do not use researchpy; it outputs a dataframe, and digging results
        # out of that just adds complexity.
        # statistics['descriptives_abs'], statistics['ttest_abs'] = rp.ttest(
        #     df['T1'], df['T2'])

    # Define class names
    cnames = ['[-100…-10[', '[-10…10]', ']10…100]']

    # Adding labels doesn't make sense as legend plotting does not work
    # (see below).
    # for i in range(len(cnames)):
    # df['Label'] = None
    #     df.loc[df['Class'] == i, 'Label'] = cnames[i]

    # Get the tile provider. Ideally I should define my own and use
    # an NLS bkg map, but defining an own WTMS source is painstaking!
    tiles = get_provider(Vendors.CARTODBPOSITRON_RETINA)
    # tiles = get_provider(Vendors.STAMEN_TERRAIN_RETINA)

    # Try to plot a map
    plot = figure(
        x_range=(2725000, 2815000),
        y_range=(8455000, 8457000),
        # x_range=(2725000,2815000),
        # y_range=(8355000,8457000),
        x_axis_type="mercator",
        y_axis_type="mercator",
        height=450,
        width=600,
        title=desc + ', ' + first + '–' + last)
    plot.add_tile(tiles, level='underlay')

    # Create the colour mapper
    colourmapper = LinearColorMapper(low=1,
                                     high=1,
                                     palette=[palettes.RdYlBu[9][4]],
                                     low_color=palettes.RdYlBu[9][0],
                                     high_color=palettes.RdYlBu[9][8])

    # Create a map source from the DB results table and plot it
    mapsource = GeoJSONDataSource(geojson=df.to_json())
    plot.patches('xs',
                 'ys',
                 fill_color={
                     'field': 'Class',
                     'transform': colourmapper
                 },
                 line_color='gray',
                 source=mapsource,
                 line_width=1,
                 level='underlay')

    # Plot labels from centroids
    labsource = GeoJSONDataSource(geojson=df_centroids.to_json())
    # DEBUG: mark centroids on maps
    # plot.circle('x', 'y', source=labsource, color='red', size=10, level='underlay')
    labels = LabelSet(x='x',
                      y='y',
                      text='RFChange',
                      text_font_size='8pt',
                      x_offset=-4,
                      y_offset=-7,
                      source=labsource,
                      level='glyph')
    plot.add_layout(labels)

    # Cite map sources
    citation = Label(
        x=3,
        y=0,
        x_units='screen',
        y_units='screen',
        text='Map data: Statistics Finland, UH / Accessibility Research Group',
        render_mode='css',
        text_font_size='7.25pt',
        text_color='black',
        border_line_color='white',
        border_line_alpha=0.1,
        border_line_width=1.0,
        background_fill_color='white',
        background_fill_alpha=0.4)
    plot.add_layout(citation)
    bkg_map_head = Label(x=298,
                         y=0,
                         x_units='screen',
                         y_units='screen',
                         text='Background map: ',
                         render_mode='css',
                         text_font_size='7.25pt',
                         text_color='black',
                         border_line_color='white',
                         border_line_alpha=0.1,
                         border_line_width=1.0,
                         background_fill_color='white',
                         background_fill_alpha=0.4)
    plot.add_layout(bkg_map_head)

    # Create a legend. Of course it does NOT work automatically, see
    # https://github.com/bokeh/bokeh/issues/9398, but MUST still be defined
    # by data. :(
    # The easiest way is to create fake elements and position them so that
    # they're invisible, but draw a legend for them anyway.
    xq = list()
    yq = list()
    for i in range(3):
        xq.append(2800000 + 1000 * i)
    for i in range(3):
        xq.append(8500000 + 1000 * i)
    colours = [
        palettes.RdYlBu[9][0], palettes.RdYlBu[9][4], palettes.RdYlBu[9][8]
    ]
    legend_renderer = plot.multi_line([xq, xq, xq], [yq, yq, yq],
                                      color=colours,
                                      line_width=20)
    legend = [
        LegendItem(label=cnames[0], renderers=[legend_renderer], index=0),
        LegendItem(label=cnames[1], renderers=[legend_renderer], index=1),
        LegendItem(label=cnames[2], renderers=[legend_renderer], index=2)
    ]
    plot.add_layout(
        Legend(items=legend, location='top_right', title='Change, %-p.'))

    hoverinfo = HoverTool()
    hoverinfo.tooltips = [('Region', '@nimi'), ('Mean time ' + first, '@T1'),
                          ('Mean time ' + last, '@T2'),
                          ('Mean time change', '@AbsChange'),
                          ('Change, %-point of the industry total',
                           '@RFChange')]

    plot.add_tools(hoverinfo)

    return plot, statistics, reshist, resqq
Beispiel #24
0
def visualization():
    # Read sqlite query results into a pandas DataFrame index
    db1 = sqlite3.connect("SQL_data/index.sqlite")
    df1 = pd.read_sql_query("SELECT * from Trails", db1)
    db1.close()

    # Set renderer for plotting
    sqlsource = ColumnDataSource(df1)
    # print(sqlsource)

    # Read in shapefile and examine data
    contiguous_usa = gpd.read_file('Data/cb_2018_us_state_20m.shp')
    # print(contiguous_usa.head())

    # Read in state population data and examine
    read_file = pd.read_excel('Data/US_State_Elev_Peaks_name.xlsx')
    read_file.to_csv('Data/US_STATE_EP.csv', index=None, header=True)
    state_elav = pd.read_csv('Data/US_STATE_EP.csv')
    # print(state_elav.head())

    # Merge shapefile with Highest Peaks data
    elav_states = contiguous_usa.merge(state_elav,
                                       left_on=["NAME"],
                                       right_on=["NAME"])

    # Drop Alaska and Hawaii
    elav_states = elav_states.loc[~elav_states['NAME'].
                                  isin(['Alaska', 'Hawaii'])]

    geosource = GeoJSONDataSource(geojson=elav_states.to_json())

    # Create figure object.
    p = figure(title='Hiking Trails Mapping',
               plot_height=600,
               plot_width=950,
               toolbar_location='right',
               tools="pan,wheel_zoom,box_zoom,reset",
               active_scroll="wheel_zoom")

    p.xgrid.grid_line_color = None
    p.ygrid.grid_line_color = None
    # Add patch renderer to figure.
    states = p.patches('xs',
                       'ys',
                       source=geosource,
                       fill_color=None,
                       line_color="gray",
                       line_width=0.25,
                       fill_alpha=1)

    # Define color palettes
    palette = brewer['BrBG'][11]
    # palette = mpl['Cividis'][10]
    # ('#440154', '#30678D', '#35B778', '#FDE724')
    palette = palette[::
                      -1]  # reverse order of colors so higher values have darker colors
    # Instantiate LinearColorMapper that linearly maps numbers in a range, into a sequence of colors.
    color_mapper = LinearColorMapper(palette=palette, low=0, high=15000)

    # Define custom tick labels for color bar.
    tick_labels = {
        "0": "0",
        "500": "500",
        "1000": "1,000",
        "1500": "1,500",
        "2500": "2,500",
        "3500": '3,500',
        "4000": "4,000",
        "7,000": "7,000",
        "10000": "10,000",
        "14,000": "14,000",
        "18000": "18,000",
        "22000": "22,000+"
    }

    # Create color bar.
    color_bar = ColorBar(color_mapper=color_mapper,
                         label_standoff=10,
                         width=500,
                         height=20,
                         border_line_color=None,
                         scale_alpha=0.5,
                         location=(0, 0),
                         orientation='horizontal',
                         major_label_overrides=tick_labels)

    # Create figure object.
    p = figure(
        title=
        'Hiking Trail Locations and Highest State Elevation Peak Data (US mainland)',
        plot_height=600,
        plot_width=950,
        toolbar_location='right',
        tools="pan, wheel_zoom, box_zoom, reset, tap")
    p.xgrid.grid_line_color = None
    p.ygrid.grid_line_color = None
    p.title.text_font_size = "6px"
    p.toolbar.active_scroll = p.select_one(WheelZoomTool)

    # Add patch renderer to figure.
    states = p.patches('xs',
                       'ys',
                       source=geosource,
                       fill_color={
                           'field': 'H_Elevation',
                           'transform': color_mapper
                       },
                       line_color='gray',
                       line_width=0.25,
                       fill_alpha=0.5)

    trails = p.circle('longitude',
                      'latitude',
                      radius=0.01,
                      source=sqlsource,
                      color="black")
    # Create Tap tool
    taptool = p.select(type=TapTool)
    # url = df[url]
    taptool.callback = OpenURL(url='@url')

    # Create hover tool (trail location circles)
    p.add_tools(
        HoverTool(renderers=[trails],
                  tooltips=[('Trail', '@name'), ('Length', '@length'),
                            ('Latitude', '@latitude'),
                            ('Longitude', '@longitude'), ("Stars", "@stars"),
                            ("URL", '@url')]))
    # Create hover tool (States and Highest Elevation)
    p.add_tools(
        HoverTool(renderers=[states],
                  tooltips=[('State', '@NAME'),
                            ('Highest Elevation', '@H_Elevation')]))

    p.add_tools
    # Add the Legend Color Bar
    p.add_layout(color_bar, 'below')
    # add text info to layout
    p.title.text_font_size = "20px"
    p.add_layout(Title(text="Legend: Altitude(feet)", align="left"), "below")
    p.add_layout(Title(text="Click on Trail for url", align="left"), "above")

    # return to ___main___
    return show(p)
Beispiel #25
0
        return '7'
    elif x==45:
        return '8'
    elif x==83:
        return '9'
    elif x==184:
        return '10'
    else:
        return '0'
    
NY_zip_count['color1']=NY_zip_count['nb_count'].map(rank_to)
values = {'neighbourhood_group': 'N/A', 'nb_count': 'N/A'}
NY_zip_count=NY_zip_count.fillna(value=values)
NY_zip_count

geosource1 = GeoJSONDataSource(geojson = NY_zip_count.to_json())

# Define color palettes
palette =['#300711', '#580C1F', '#CC0000','#9C0D38', '#FF5A5F', '#F26F80', 
          '#CC8B86', '#F9B5AC', '#FAC9C2', '#FCE6EC', '#E0E0E0']

# reverse order of colors so higher values have darker colors
palette = palette[::-1]

# Instantiate Categorical ColorMapper that linearly maps numbers in a range, into a sequence of colors.
color_mapper = LinearColorMapper(palette = palette,low=0,high=10)

def map2():
#Create figure object
    p2 = figure(title = 'Hotels in Manhattan', 
           plot_height = 750 ,
Beispiel #26
0
        try:
            return float(cities[cities['Ville'] == x]['Latitude'])
        except TypeError:
            return None

    def find_long(x):
        try:
            return float(cities[cities['Ville'] == x]['Longitude'])
        except TypeError:
            return None

    summary = df[['Positif', 'Ville']].groupby("Ville").sum().reset_index()
    summary['latitude'] = summary['Ville'].apply(lambda x: find_lat(x))
    summary['longitude'] = summary['Ville'].apply(lambda x: find_long(x))

    geosource = GeoJSONDataSource(geojson=grid)
    pointsource = ColumnDataSource(summary)

    hover = HoverTool(
        tooltips=[('Ville',
                   '@Ville'), ('Nombre de cas positifs (au moins)',
                               '@Positif')])

    #Create figure object.
    p = figure(plot_height=550,
               plot_width=700,
               tools=[hover, 'pan', 'wheel_zoom'])
    p.xgrid.grid_line_color = None
    p.ygrid.grid_line_color = None
    p.xaxis.visible = False
    p.yaxis.visible = False
Beispiel #27
0
def map_tab(map_all_data, score_types_list, sources_list):
    # Filter data we start with
    score_type_filter = 'InSample'  #'OOS'
    source_filter = 'Best'
    geosource = GeoJSONDataSource(geojson = \
        map_all_data[score_type_filter + '|' + source_filter].geojson)

    ## Map formatting ##################
    palette = Viridis256  # brewer["Spectral"][8] # Category20[20] # brewer["PRGn"][11]
    color_mapper = LinearColorMapper(palette=palette, low=-1, high=1)
    color_bar = ColorBar(color_mapper=color_mapper,
                         width=650,
                         height=20,
                         formatter=NumeralTickFormatter(format=",0.00"),
                         border_line_color=None,
                         orientation='horizontal',
                         location=(0, 0))
    hover = HoverTool(tooltips=[('Region', '@Region'), ('Value', '@Value')])

    #Create figure object.
    width = 750
    height = np.int(width * 13 / 15)
    p = figure(title='Venezuela Situational Awareness',
               plot_height=height,
               plot_width=width,
               tools=[hover, "pan,wheel_zoom,box_zoom,reset"],
               toolbar_location="left")

    p.xgrid.grid_line_color = None
    p.ygrid.grid_line_color = None

    #Add patch renderer to figure.
    p.patches('xs',
              'ys',
              source=geosource,
              fill_color={
                  'field': 'Value',
                  'transform': color_mapper
              },
              line_color='white',
              line_width=1,
              fill_alpha=0.7)
    #Specify figure layout.
    p.add_layout(color_bar, 'below')

    ## Radio buttons
    # Define buttons
    score_types = score_types_list.tolist()
    score_type_button = RadioButtonGroup(labels=score_types, active=0)
    data_sources = sources_list.tolist()
    sources_button = RadioButtonGroup(labels=data_sources, active=0)

    # Update function
    def score_type_callback(attr, old, new):
        # Get new selected value
        #new_score = score_types[new.active]
        new_score = score_types[score_type_button.active]
        new_source = data_sources[sources_button.active]
        new_key = new_score + '|' + new_source
        geosource_new = map_all_data[new_key]
        geosource.geojson = geosource_new.geojson

    # Update events
    score_type_button.on_change('active', score_type_callback)
    sources_button.on_change('active', score_type_callback)

    # Figure formatting
    set_stype(p)

    # Put controls in a single element
    controls = WidgetBox(score_type_button, sources_button)

    # Create a row layout
    layout = column(controls, p)

    # Make a tab with the layout
    tab = Panel(child=layout, title='Map of Scores')

    return tab
Beispiel #28
0
merged = gdf.merge(df_2016,
                   left_on='country_code',
                   right_on='code',
                   how='left')

#Replace NaN values to string 'No data'.
merged.fillna('No data', inplace=True)

#Read data to json
merged_json = json.loads(merged.to_json())

#Convert to str like object
json_data = json.dumps(merged_json)

#Input GeoJSON source that contains features for plotting.
geosource = GeoJSONDataSource(geojson=json_data)

#Define a sequential multi-hue color palette.
palette = brewer['YlGnBu'][8]

#Reverse color order so that dark blue is highest obesity.
palette = palette[::-1]

#Instantiate LinearColorMapper that linearly maps numbers in a range, into a sequence of colors.
color_mapper = LinearColorMapper(palette=palette, low=0, high=40)

#Define custom tick labels for color bar.
tick_labels = {
    '0': '0%',
    '5': '5%',
    '10': '10%',
Beispiel #29
0
    df1_yr = df1[df1['yr'] == yr]
    df2_yr = df2[df2['yr'] == yr]
    merged1 = gdf.merge(df1_yr, left_index=True, right_on='LGA', how='left')
    merged1.fillna({'beta_ndifgdp': 'No data'}, inplace=True)
    merged2 = gdf.merge(df2_yr, left_index=True, right_on='LGA', how='left')
    merged2.fillna({'beta_ndifpop': 'No data'}, inplace=True)
    merged_json1 = json.loads(merged1.to_json())
    json_data1 = json.dumps(merged_json1)
    merged_json2 = json.loads(merged2.to_json())
    json_data2 = json.dumps(merged_json2)
    return json_data1, json_data2


#Input GeoJSON source that contains features for plotting.
json1, json2 = json_data(2001)
geosource1 = GeoJSONDataSource(geojson=json1)
geosource2 = GeoJSONDataSource(geojson=json2)
#Define a sequential multi-hue color palette.
palette = brewer['YlGnBu'][8]
#Reverse color order so that dark blue is highest coefficient.
palette = palette[::-1]
#Instantiate LinearColorMapper that linearly maps numbers in a range, into a sequence of colors. Input nan_color.
color_mapper1 = LinearColorMapper(palette=palette,
                                  low=0,
                                  high=10,
                                  nan_color='#d9d9d9')
color_mapper2 = LinearColorMapper(palette=palette,
                                  low=-0.3,
                                  high=0.5,
                                  nan_color='#d9d9d9')
#Add hover tool
Beispiel #30
0
# The plot server must be running (`bokeh serve`) then run this script to push to it

import time
import json

from bokeh.client import push_session
from bokeh.io import curdoc
from bokeh.models import GeoJSONDataSource
from bokeh.plotting import figure
from bokeh.sampledata.sample_geojson import geojson as original

p = figure(tools='box_select')
source = GeoJSONDataSource(geojson=original)
p.circle(line_color=None, fill_alpha=0.8, source=source)

# Open a session which will keep our local doc in sync with server
session = push_session(curdoc())

# Open the session in a browser
session.show()

is_original = True

while True:
    if is_original:
        # update to something else
        source.geojson = json.dumps(
            {'type': 'FeatureCollection',
             'features': [
                 {"type": "Feature",
                  "geometry": {"type": "Point",
                  'field': ward_name,
                  'transform': color_mapper
              },
              line_color='black',
              line_width=0.25,
              fill_alpha=1)

    # Specify color bar layout.
    p.add_layout(color_bar, 'below')
    # Add the hover tool to the graph
    p.add_tools(hover)

    return p


geosource = GeoJSONDataSource(geojson=json_data('2019-06-01'))

# Input geojson source that contains features for plotting for:
# initial year 2018 and initial criteria sale_price_median
ward_name = 'total'
all_wards_names = [
    'total', 'mental_health', 'maternity', 'learning_dis', 'general_acute'
]

# Define a sequential multi-hue color palette.
palette = brewer['Blues'][8]

# Reverse color order so that dark blue is highest obesity.
palette = palette[::-1]

# Add hover tool