python-visualization / folium

Python Data. Leaflet.js Maps.
https://python-visualization.github.io/folium/
MIT License
6.85k stars 2.22k forks source link

ValueError: blue is not a valid ColorBrewer code #1166

Closed Gustacro closed 1 year ago

Gustacro commented 5 years ago

Please add a code sample or a nbviewer link, copy-pastable if possible

# Your code here
def my_colors(feature):
    """Postcodes will be colored based on the drive time assigned to """
def my_colors(feature):
    """Postcodes will be colored based on the drive time assigned to """
    if drive_time[feature['drv_tm']] == 30:
        return #1b9e77
    if drive_time[feature['drv_tm']] == 45:
        return #d95f02
    if drive_time[feature['drv_tm']] == 60:
        return #7570b3
    if drive_time[feature['drv_tm']] == 75:
        return #e7298a
    if drive_time[feature['drv_tm']] == 90:
        return #66a61e
    if drive_time[feature['drv_tm']] == 120:
        return #e6ab02
    else: 
        return #a6761d    

style_function=lambda feature:{
        'fillColor': my_colors(feature)
        ,'color': 'black'
        ,'weight': 2
        }  

style_function=lambda feature:{
        'fillColor': my_colors(feature)
        ,'color': 'black'
        ,'weight': 2
        }

layer= folium.features.Choropleth(
    geo_data= gjson_dt # gjson_dt, is the geojson feature object created from the geodataframe
    ,data=drive_time #dataframe that contain the postgres table related to the geojson file
    ,style_function= style_function
    ,name= 'drv_time' # name of the layer
    ,key_on='feature.properties.postcode' # Feature ID of the dataframe in this case 'postcode'
    ,columns= ['postcode', 'drv_tm']# column to use for the choropleth
    ,highlight=True # highlight the polygon and zoom in to it when you click on the polygon
    ,legend_name='Drive Time' # legend name
m.add_child(layer)

Problem description

I'm trying to display a thematic map with folium using values from a column and a function (color ramp) but I'm getting ValueError: blue is not a valid ColorBrewer code as result.

[this should explain why the current behavior is a problem and what is the expected output.]

Expected Output

I'm expecting to get a map with specific color based on a column ['drv_tm'] values and function that contain the color ramp

Output of folium.__version__

0.8.3

fullonic commented 5 years ago

@Gustacro can you place here all the output error? I think that what is creating your error is the Choropleth default value of fill_color=blue.

From Choropleth docstring:

   fill_color: string, default 'blue'
        Area fill color. Can pass a hex code, color name, or if you are
        binding data, one of the following color brewer palettes:
        'BuGn', 'BuPu', 'GnBu', 'OrRd', 'PuBu', 'PuBuGn', 'PuRd', 'RdPu',
        'YlGn', 'YlGnBu', 'YlOrBr', and 'YlOrRd'.

But in fact, currently, only the brewer palettes codes are working. Passing a color hex code gives the same error.

Gustacro commented 5 years ago

the full error message is this: `--------------------------------------------------------------------------- ValueError Traceback (most recent call last)

in 15 # ,fill_opacity= 0.7 16 # ,line_opacity= 0.2 ---> 17 ,highlight=True # highlight the polygon and zoom in to it when you click on the polygon 18 ) 19 # add popups to the map C:\ProgramData\Anaconda3\lib\site-packages\folium\features.py in __init__(self, geo_data, data, columns, key_on, bins, fill_color, nan_fill_color, fill_opacity, nan_fill_opacity, line_color, line_weight, line_opacity, name, legend_name, overlay, control, show, topojson, smooth_factor, highlight, **kwargs) 932 self._name = 'Choropleth' 933 --> 934 if data is not None and not color_brewer(fill_color): 935 raise ValueError('Please pass a valid color brewer code to ' 936 'fill_local. See docstring for valid codes.') C:\ProgramData\Anaconda3\lib\site-packages\branca\utilities.py in color_brewer(color_code, n) 147 148 if base_code not in core_schemes: --> 149 raise ValueError(base_code + ' is not a valid ColorBrewer code') 150 151 try: ValueError: blue is not a valid ColorBrewer code ` The only way that I was able to work around was defining a threshold [30,45,60,75,90,120,150], but unfortunately I have to used brewer palettes colors and not the colors defined in my function (my_colors). It there another way to use custome color ramp?
Conengmo commented 5 years ago

If you use one of the color brew palettes does it work?

'BuGn', 'BuPu', 'GnBu', 'OrRd', 'PuBu', 'PuBuGn', 'PuRd', 'RdPu', 'YlGn', 'YlGnBu', 'YlOrBr', and 'YlOrRd'

Choropleth(fill_color='BuGn')

I'm thinking maybe we should recover automatically, with a warning, if somebody provides data but doesn't use a color brew palette instead of raising an exception. Or the error message should contain some hint on how to resolve.

fullonic commented 5 years ago

@Conengmo it works. Looks like that Choropleth only accepts brew pallets codes. I went back to see how it was done in early versions, and the line of code that breaks now, is the same as it was back on versions like 2 or 3.

if data is not None and not color_brewer(fill_color):
    raise ValueError('Please pass a valid color brewer code to '
    'fill_local. See docstring for valid codes.')

Also, "fill_local" in the error message should be "fill_color", right?

@Gustacro, you are using the style_function parameter when in reality looks like that is not supported by Choropleth.

Conengmo commented 5 years ago

Looks like that Choropleth only accepts brew pallets codes.

If you provide a dataframe it only accepts those. Otherwise a 'normal' color works.

Also, "fill_local" in the error message should be "fill_color", right?

Indeed. But, that error message doesn't trigger because an error is already raised in color_brewer(). Maybe use a try/except here and include the list of valid codes in the error message? What do you think?

fullonic commented 5 years ago

Ahh okay, now I tried without passing data and it works with color "blue". So we should alert on the error message what codes are available and why it doesn't work with a color name or hex code.

Here would you include the try/except block? If we do it here: https://github.com/python-visualization/folium/blob/f05f3ce9b3d71f87a0738f3c8c1236b933e497a9/folium/features.py#L1046-L1048

it will break again here: https://github.com/python-visualization/folium/blob/f05f3ce9b3d71f87a0738f3c8c1236b933e497a9/folium/features.py#L1088

What do you think that is better, break the code and give an error message with more information, or do a try/except block, alert the user with a warning and generate a fill_color with a brew pallet code? Something like this:

try:
    if data is not None and not color_brewer(fill_color):
        pass
except Exception as e:
    print(e)
    fill_color = "PuBu"
    warnings.warn(
                  [error message and why] 
                  Please choose one from the list below:\n'
                  '["Spectral", "RdYlGn", "PuBu", (...)]\n'
                  '"PuBu" brew color pallet was setup automatically for you.')

Another question, do you think that would be harder import the style_function from GeoJson to Choropleth?

Gustacro commented 5 years ago

@Conengmo it works. Looks like that Choropleth only accepts brew pallets codes. I went back to see how it was done in early versions, and the line of code that breaks now, is the same as it was back on versions like 2 or 3.

if data is not None and not color_brewer(fill_color):
    raise ValueError('Please pass a valid color brewer code to '
    'fill_local. See docstring for valid codes.')

Also, "fill_local" in the error message should be "fill_color", right?

@Gustacro, you are using the style_function parameter when in reality looks like that is not supported by Choropleth.

@Conengmo, I did at first, using a custom color ramp function (my_colors), didn't know that it wasn't supported by Choropleth, then I used threshold scale and colorbrewer palette. It would be useful if Choropleth support style_function to be able to use custom color ramp.

Conengmo commented 1 year ago

Pretty sure the original issue has been solved by https://github.com/python-visualization/folium/pull/1288