|
|
|
import solara |
|
from ipyleaflet import Map, GeoJSON, GeoData, LayersControl, Marker, MarkerCluster, basemaps, Choropleth |
|
from branca.colormap import linear |
|
import plotly.express as px |
|
import matplotlib |
|
import geopandas as gpd |
|
import pandas as pd |
|
import numpy as np |
|
from shapely import wkt |
|
import json |
|
import re |
|
|
|
|
|
df = pd.read_csv('./data/pois_final_control.csv') |
|
df = df[(df['EnEstudio'] == True)] |
|
df = df[df['Geometry'].notnull()] |
|
df['geometry'] = df['Geometry'].apply(wkt.loads) |
|
pois = gpd.GeoDataFrame(df, geometry='geometry') |
|
pois = pois.set_crs(epsg=4326, inplace=True) |
|
pois = pois.drop('EnEstudio', axis=1) |
|
pois = pois.drop('Geometry', axis=1) |
|
|
|
|
|
df1 = pd.read_csv('./data/poiscount_r8hex_large.csv', index_col=0) |
|
df1 = df1[df1['Conteo'] > 0] |
|
df1 = df1.drop('EnEstudio', axis=1) |
|
df1['geometry'] = df1['geometry'].apply(wkt.loads) |
|
h3 = gpd.GeoDataFrame(df1, geometry='geometry') |
|
h3 = h3.set_crs(epsg=4326, inplace=True) |
|
|
|
|
|
cantones = [str(k) for k in pois['Canton'].unique().tolist()] |
|
categorias = [str(k) for k in pois['Categoria'].unique().tolist()] |
|
canton = solara.reactive('QUITO') |
|
categoria = solara.reactive('salud') |
|
limit = solara.reactive(2500) |
|
|
|
|
|
def data_filter(df, city, category): |
|
df_filtered = df.loc[df['Canton']==city] |
|
df_filtered = df_filtered[df_filtered['Categoria']==category] |
|
return df_filtered |
|
|
|
|
|
def ipyleaflet_map(geo_df, h3_df, h3_geojson): |
|
|
|
center = (geo_df.geometry.y.mean(), geo_df.geometry.x.mean()) |
|
zoom = 11 |
|
|
|
m = Map(center=center, zoom=zoom) |
|
|
|
|
|
services = GeoData( |
|
geo_dataframe=geo_df, |
|
style={ |
|
'color': 'black', |
|
'radius': 7, |
|
'fillColor': '#3366cc', |
|
'opacity': 0.5, |
|
'weight': 1.9, |
|
'dashArray': '2', |
|
'fillOpacity': 0.6 |
|
}, |
|
hover_style={ |
|
'fillColor': 'red', |
|
'fillOpacity': 0.2 |
|
}, |
|
point_style={ |
|
'radius': 7, |
|
'color': 'red', |
|
'fillOpacity': 0.8, |
|
'fillColor': 'blue', |
|
'weight': 3 |
|
}, |
|
name='Servicios de Apoyo' |
|
) |
|
|
|
|
|
colormap = linear.YlOrRd_04.scale(min(h3_df['Conteo']), max(h3_df['Conteo'])) |
|
choro_data = dict(zip(h3_df.index.astype(str), h3_df['Conteo'])) |
|
h3_choropleth = Choropleth( |
|
geo_data=h3_geojson, |
|
choro_data=choro_data, |
|
colormap=colormap, |
|
border_color='black', |
|
style={'fillOpacity': 0.8, 'dashArray': '5, 5'}, |
|
name='Densidad' |
|
) |
|
|
|
|
|
m.add_layer(services) |
|
m.add_layer(h3_choropleth) |
|
|
|
|
|
markers = [Marker(location=(point.y, point.x)) for point in geo_df.geometry] |
|
|
|
|
|
marker_cluster = MarkerCluster(markers=markers, name='Cluster Markers') |
|
m.add_layer(marker_cluster) |
|
|
|
|
|
m.add_control(LayersControl()) |
|
|
|
|
|
display(m) |
|
|
|
|
|
def type_chart_plotly(df): |
|
tipo_counts = df['Tipo'].value_counts().sort_values(ascending=True) |
|
|
|
fig = px.bar(tipo_counts, orientation='h', |
|
x=tipo_counts.values, y=tipo_counts.index, |
|
labels={'x': 'Conteo', 'y': 'Tipo'}, |
|
title='Servicios') |
|
solara.FigurePlotly(fig) |
|
|
|
|
|
@solara.component |
|
def View(): |
|
dff = data_filter(pois, canton.value, categoria.value) |
|
h3f = data_filter(h3, canton.value, categoria.value) |
|
geo_json_H3 = json.loads(h3f.to_json()) |
|
row_count = len(dff) |
|
if row_count > limit.value: |
|
solara.Warning(f"Only showing the first {limit.value} of {row_count:,} services on map") |
|
ipyleaflet_map(dff.iloc[:limit.value], h3f, geo_json_H3) |
|
if row_count > 0: |
|
with solara.Card(''): |
|
type_chart_plotly(dff) |
|
else: |
|
solara.Warning("You filtered out all the data, no charts shown") |
|
|
|
|
|
@solara.component |
|
def Controls(): |
|
solara.Select('Cantón', values=cantones, value=canton) |
|
solara.Select('Categoría', values=categorias, value=categoria) |
|
|
|
solara.Text("Maximum number of pois to show on map") |
|
solara.SliderInt('', value=limit, min=1, max=5000) |
|
|
|
|
|
@solara.component |
|
def Page(): |
|
with solara.Column(): |
|
solara.Title('Servicios de Apoyo para Migrantes') |
|
with solara.Sidebar(): |
|
with solara.Card('Filtros'): |
|
with solara.Column(): |
|
Controls() |
|
View() |
|
Page() |