In the application (visualization of natural disaster data) I am working on, I have to color the countries in the map according to a well specified data, and for that I have written the following code:
disaster_data = pd.read_csv("Data/Preprocessed-Natural-Disasters.csv", delimiter=";")
gdp_disaster_data = pd.read_csv("Data/Analysis-Preprocessing/gdp_data.csv")
gdp_data = pd.read_csv('./Data/gdp_data_constant.csv')
# Aggregating by Zone
df = gdp_disaster_data.groupby('ISO').sum()
df = gdp_disaster_data.reset_index(drop=False)
DATA_PATH='MVP-Rafael/countries.json'
with open(DATA_PATH, "r") as file:
geo_world = json.load(file)
# Instanciating necessary lists
found = []
missing = []
countries_geo = []
# For simpler acces, setting "zone" as index in a temporary dataFrame
tmp = df.set_index('ISO')
# Define a style function to determine the color based on the value in the DataFrame
def style_function(feature):
country_name = feature["properties"]["ISO_A3"]
if country_name in tmp.index:
value = tmp.loc[country_name, "share"]
# Adjust the column name above to match the relevant column in your DataFrame
# You can also apply any custom logic to determine the color based on the value
color = "red" if value > 100 else "green"
else:
color = "gray" # Set a default color for missing countries
return {
"color": color,
"fillOpacity": 0.6
}
# Looping over the custom GeoJSON file
for country in geo_world['features']:
country_name = country['properties']['ISO_A3']
if country_name in tmp.index:
found.append(country_name)
geometry = country['geometry']
country_geo = {
'type': 'Feature',
'geometry': geometry,
'properties': {
'country_name': country_name,
'share_value': tmp.loc[country_name, 'share']
# Adjust the column name above to match the relevant column in your DataFrame
}
}
countries_geo.append(country_geo)
else:
missing.append(country_name)
# Displaying metrics
print(f'Countries found : {len(found)}')
print(f'Countries not found: {len(missing)}')
geo_world_ok = {'type': 'FeatureCollection', 'features': countries_geo}
map = dl.Map(
maxBounds=[[-90, -180], [90, 180]],
maxBoundsViscosity=1.0,
maxZoom=18,
minZoom=2,
center=(40, -37),
bounceAtZoomLimits=True,
children=[
dl.TileLayer(),
# https://datahub.io/core/geo-countries#resource-countries
dl.GeoJSON(
data=util.get_world_geojson(),
id="countries",
# Invisible polygons,
options={"style": {"color": "transparent"}},
zoomToBounds=True,
hoverStyle=arrow_function(dict(weight=3, color='#666', dashArray=''))), # Gray border on hover (line_thickness, color, line_style)
dl.LayersControl([
dl.Colorbar(colorscale="viridis", width=20, height=150, min=0, max=16,unit='m/s',position="bottomleft")]),
dl.GeoJSON(
data=geo_world_ok,
id="gdp-colour",
options={"style": style_function} # Apply the style function to determine the color
),
dl.GeoJSON(data={},
id="events",
options=dict(pointToLayer=ns("draw_marker"))),
map_legend,
world_slider_wrapper
],
style={"width": "100%", "height": "100%", "display": "block"},
id="map")
And here is the callback function I tried to write, knowing that this is the first time I'm doing a dash leaflet:
@app.callback(
Output("gdp-colour", "children"),
Input("world-year-slider", "value")
)
def update_map(selected_year):
filtered_df = df[df.year == selected_year]
def style_function(feature):
country_name = feature["properties"]["ISO_A3"]
if country_name in filtered_df["ISO"].values:
value = filtered_df.loc[filtered_df["ISO"] == country_name, "share"].values[0]
color = "red" if value > 100 else "green"
else:
color = "gray"
return {
"color": color,
"fillOpacity": 0.6
}
return style_function
But I am getting the following error and the map is not displayed :
"Callback error updating content.children"
The csv file and geojson data I merged work fine, but the problem is that the map is not even displayed knowing that I want to display it by colouring the countries according to a well specified column in the data.