plotly / plotly.py

The interactive graphing library for Python :sparkles: This project now includes Plotly Express!
https://plotly.com/python/
MIT License
16.26k stars 2.55k forks source link

Choropleth only displaying one color in custom geojson #2619

Closed COYE-Coder closed 4 years ago

COYE-Coder commented 4 years ago

I am trying to create a choropleth using plotly.express. The figure is able to load, but it only shows one color. I can mouse over each feature and it displays the relevant information, but not in variable color. This implies that it is reading the geojson but not displaying properly. Here is my stackoverflow thread I created earlier.

I am using the featureidkey parameter with a geojson (hucs) that should match with the DataFrame (predictions).

Here is predictions:

import pandas as pd
predictions = pd.read_csv("Predictions_DF_2002.csv")

predictions.head()
huc12           Predicted PRBT   Std
170102120304    30.677075        23.348831
170102120603    31.362211        23.784001
90400010201     5.697461         7.688427
100301040401    3.493039         5.36472
170101011208    4.421055         11.924093

And here is the code for reading in the geojson (hucs):

#Read in geojson
import geopandas as gpd
import json

hucs = gpd.read_file(~/"HUC.geojson")

#Populate hucs['properties'] (i.e. convert to plotly-readible geojson-type)
hucs = json.loads(hucs.to_json())

#Print Properties for sanity check
print(hucs['features'][0]['properties'])
#...<a bunch of stuff we don't care about> 
{'huc12':170102120304}
#...

I followed the example here to index by geojson properties:

fig = px.choropleth(predictions,
                    geojson=hucs, color='Predicted PRBT',
                    locations='huc12', featureidkey='properties.huc12',
                    color_continuous_scale="Viridis", labels={'Predicted PRBT':'Predicted % RBT'})
fig.update_geos(fitbounds="locations",visible=False)
fig.show()

And here is what the output shows. Note that mouse-over shows relevant information, but no colors are displayed:

image

My csv and geojson are available for download here.

Many thanks in advance for the help!

nicolaskruchten commented 4 years ago

The issue appears to be with your GeoJSON file, which is "wound" the wrong way... see https://github.com/plotly/plotly.py/issues/2354#issuecomment-638742767 for a fix.

nicolaskruchten commented 4 years ago

image

COYE-Coder commented 4 years ago

That solved it, thank you!

nicolaskruchten commented 3 years ago

Here's more copy-pasteable code for starting from a badly-wound GeoPandas dataframe:

import json
import geojson_rewind
import geopandas as gpd

gdf = gpd.read_file("badly_wound.json")

gdf = gdf.set_geometry(
    gpd.GeoDataFrame.from_features(
        json.loads(
            geojson_rewind.rewind(
                gdf.to_json(), 
                rfc7946=False
            )
        )["features"]
    ).geometry
)
ColdTeapot273K commented 8 months ago

Here's more copy-pasteable code for starting from a badly-wound GeoPandas dataframe:

import json
import geojson_rewind
import geopandas as gpd

gdf = gpd.read_file("badly_wound.json")

gdf = gdf.set_geometry(
    gpd.GeoDataFrame.from_features(
        json.loads(
            geojson_rewind.rewind(
                gdf.to_json(), 
                rfc7946=False
            )
        )["features"]
    ).geometry
)

This can sometimes produce dataframe with empty geometry column.

Somewhat more robust way:

igdf = gdf.set_geometry(
    gpd.GeoDataFrame.from_features(
        json.loads(
            geojson_rewind.rewind(
                gdf.to_json(), 
                rfc7946=False
            )
        )["features"]
    ).geometry.values
)

Tested on: