0

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.

enter image description here

felipsmartins
  • 13,269
  • 4
  • 48
  • 56
M_EL
  • 1
  • I would be easier to help if you could post a minimal working example (MWE), i.e. a small piece of code that demonstrates the issue. One bug that is apparent from your current code snippet though is that you pass a Python function to the GeoJSON style option, it must be a JavaScript function (like the one you pass to pointToLayer). – emher Aug 25 '23 at 11:49

0 Answers0