I've found a solution on my own and also an answer in the following discussion on GitHub:
https://github.com/python-visualization/folium/issues/1303#issuecomment-675368594
1) Own solution
## * Create a gradient dictionary adapted to the colormap plotted previously * ##
# Instantiate empty dictionary
perc_color_gradient_dict = {}
color_gradient_dict = {}
size_gradient_dict = {}
max_size_val = 12
# Loop over index-values and according colors in RGBA-vector-space
for ind_val, c in zip(colormap.index, colormap.colors):
# Calculate the percentile of the current index value as the gradient dictionary takes
# only percentages of the entire value range, not the absolute values themselves
perc_val = (ind_val - min_z) / ((max_z - min_z))
# * Get the hex-color, if desired -> PREFERRED
# NOTE on scope of choosing hex-colors over actual color-names:
# The colorname space is very small for built-in folium plugins, wherefore only standard names can be passed
# to the employed functions, e.g. via the color_gradient_dict for adaptation to the colormap
# -> Here, hex-colors come in handy as they can be interpreted by folium.plugins
# NOTE on former approach:
# Get the actual or closest colorname fitting to the current color
# actual_c_name, closest_c_name = aux_plot.get_exact_or_closest_colorname_to_RGB_color(c)
hex_color = aux_plot.convert_given_color_to_RGB_RGBA_hex_or_HSV(
c, return_type="hex", keep_alpha=keep_alpha)
# Add it to the color_gradient_dicts
# NOTE on scope: this is only for information purposes, it'll be printed out below
perc_color_gradient_dict[perc_val] = hex_color
color_gradient_dict[ind_val] = hex_color
# Finally, create an size-gradient dictionary alongside with the color dicts
size_gradient_dict[ind_val] = perc_val * max_size_val
def value_filter_from_dict(val, gradient_dict=None):
range_limit_keys = np.array(sorted(list(gradient_dict.keys())))
filtered_array = range_limit_keys[val < range_limit_keys]
if len(filtered_array) > 0:
left_border_key = min(filtered_array)
else:
left_border_key = max(range_limit_keys)
return gradient_dict[left_border_key]
# NOTE on implementation syntax:
# If avoiding lambda is a concern, .apply(value_filter_from_dict, gradient_dict=color_gradient_dict) also does the job
# https://stackoverflow.com/questions/52673285/performance-of-pandas-apply-vs-np-vectorize-to-create-new-column-from-existing-c
# -> use key
df['color'] = df[z_varname_new].swifter.apply(
lambda val: value_filter_from_dict(val, gradient_dict=color_gradient_dict))
df['size'] = df[z_varname_new].swifter.apply(
lambda val: value_filter_from_dict(val, gradient_dict=size_gradient_dict))
In the following, the printouts for each color-gradient dictionary are displayed.
## * Printout for user * ##
# In:
print(
f"\nThe final percentage color gradient dictionary is:\n{perc_color_gradient_dict}"
)
print(f"\nThe final color gradient dictionary is:\n{color_gradient_dict}")
print(f"\nThe final size gradient dictionary is:\n{size_gradient_dict}")
# Out:
The final percentage color gradient dictionary is:
{0.0: '#ffffb2', 0.05: '#fff7a4', 0.1: '#ffef97', 0.15000000000000002: '#ffe789', 0.2: '#fedf7c', 0.25: '#fed76e', 0.30000000000000004: '#fecf61', 0.35000000000000003: '#fec559', 0.4: '#febb54', 0.45: '#feb14f', 0.5: '#fda849', 0.55: '#fd9e44', 0.6000000000000001: '#fd943f', 0.65: '#fc873a', 0.7000000000000001: '#f87535', 0.75: '#f36330', 0.8: '#ef502b', 0.85: '#eb3e26', 0.9: '#e72c21', 0.95: '#e31a1c'}
The final color gradient dictionary is:
{1.4304179517249468e-05: '#ffffb2', 0.000263588970541387: '#fff7a4', 0.0005128737615655246: '#ffef97', 0.0007621585525896622: '#ffe789', 0.0010114433436137996: '#fedf7c', 0.001260728134637937: '#fed76e', 0.0015100129256620748: '#fecf61', 0.0017592977166862123: '#fec559', 0.0020085825077103495: '#febb54', 0.002257867298734487: '#feb14f', 0.0025071520897586245: '#fda849', 0.002756436880782762: '#fd9e44', 0.0030057216718069: '#fd943f', 0.0032550064628310373: '#fc873a', 0.003504291253855175: '#f87535', 0.0037535760448793123: '#f36330', 0.00400286083590345: '#ef502b', 0.004252145626927588: '#eb3e26', 0.004501430417951725: '#e72c21', 0.004750715208975863: '#e31a1c'}
The final size gradient dictionary is:
{1.4304179517249468e-05: 0.0, 0.000263588970541387: 0.6000000000000001, 0.0005128737615655246: 1.2000000000000002, 0.0007621585525896622: 1.8000000000000003, 0.0010114433436137996: 2.4000000000000004, 0.001260728134637937: 3.0, 0.0015100129256620748: 3.6000000000000005, 0.0017592977166862123: 4.2, 0.0020085825077103495: 4.800000000000001, 0.002257867298734487: 5.4, 0.0025071520897586245: 6.0, 0.002756436880782762: 6.6000000000000005, 0.0030057216718069: 7.200000000000001, 0.0032550064628310373: 7.800000000000001, 0.003504291253855175: 8.4, 0.0037535760448793123: 9.0, 0.00400286083590345: 9.600000000000001, 0.004252145626927588: 10.2, 0.004501430417951725: 10.8, 0.004750715208975863: 11.399999999999999}
Finally, for the sake of completeness, I'm going to post the details of the previously employed function convert_given_color_to_RGB_RGBA_hex_or_HSV()
:
def convert_given_color_to_RGB_RGBA_hex_or_HSV(color,
return_type="rgb",
rgb_n_rgba_as_int=False,
keep_alpha=True,
alpha=None):
"""Function documentation:\n
Accepts the following input and output color formats:
- HSV (see: https://en.wikipedia.org/wiki/HSL_and_HSV)
- RGB
- RGBA
- hex
- color-name (string)
# NOTE on return type preference:
Prefer matplotlib- over webcolors-return-type within the realm of python
# NOTE on hex-type as the choice for in-between conversion step:
-> This is the link between both worlds of matplotlib and webcolors which works for both,
i.e. which is compatible between both libraries
"""
# Check whether a correct value has been passed as return-type
if return_type.lower() not in ["rgb", "rgba", "hsv", "hex"]:
raise Exception(
f"The given return type '{return_type}' has not been implemented.")
else:
return_type = return_type.lower() # saves coding later
# Save initial color for later error-message, if necessary
original_color = color
# * i) String
if isinstance(color, str):
## CONVERT to hex-type
# I) Indicates the case of a hex-color, such as '#08519c'
if "#" in color:
pass # is already of hex-type (compatible with everything)
# II) Considers percent-string-triplets, such as (u'100%', u'100%', u'100%')
elif "%" in color:
# NOTE: use the hex-type as connective link between both libraries
color = webcolors.rgb_percent_to_hex(color) # convert to hex-type
# III) Any other name provided like "black"
else:
# NOTE: use the hex-type as connective link between both libraries
color = webcolors.name_to_hex(color) # convert to hex-type
if alpha is not None and keep_alpha:
color = mpl.colors.to_hex(mpl.colors.to_rgba(color,
alpha=alpha),
keep_alpha=keep_alpha)
# * ii) HSV, RGB or RGBA
else:
## CONVERT to hex-type
# NOTE on keep_alpha: refers to the alpha information of a passed color, like the 4D-RGBA-vectors
color = mpl.colors.to_hex(color, keep_alpha=keep_alpha)
## * 0) Special previous check for hex-type
if return_type == "hex":
return color # is already hex
## * 1) Matplotlib
try:
# Distinguish between the different return types
if return_type == "rgb":
if not rgb_n_rgba_as_int: # as percent
return mpl.colors.to_rgb(color)
else:
# NOTE: use webcolors for integer RGB-colors without alpha
# CAUTION: as webcolors cannot handle alpha values, convert possible alpha-hex to normal hex prior to passing them to webcolors-functions
rgb_as_int = webcolors.hex_to_rgb(
mpl.colors.to_hex(mpl.colors.to_rgb(color)))
return (rgb_as_int.red, rgb_as_int.green, rgb_as_int.blue)
elif return_type == "rgba":
if not rgb_n_rgba_as_int: # as percent
return mpl.colors.to_rgba(color, alpha=alpha)
else:
# NOTE: use webcolors for integer RGB-colors without alpha
# CAUTION: as webcolors cannot handle alpha values, convert possible alpha-hex to normal hex prior to passing them to webcolors-functions
rgb_as_int = webcolors.hex_to_rgb(
mpl.colors.to_hex(mpl.colors.to_rgb(color)))
return (rgb_as_int.red, rgb_as_int.green, rgb_as_int.blue,
alpha)
elif return_type == "hsv":
return mpl.colors.rgb_to_hsv(mpl.colors.to_rgb(color))
## * 2) Webcolors
# NOTE on possible return values: webcolors doesn't have RGBA- and HSV-support
except:
# Distinguish between the different return types
if return_type == "rgb":
# NOTE: use webcolors for integer RGB-colors without alpha
# CAUTION: as webcolors cannot handle alpha values, convert possible alpha-hex to normal hex prior to passing them to webcolors-functions
return webcolors.hex_to_rgb(
mpl.colors.to_hex(mpl.colors.to_rgb(color)))
# If this part of the code is reached, something went wrong and it would return None
raise Exception(
f"No proper color could be returned for the given color '{original_color}'."
)
2) Answer from GitHub
From there, I'm going to mention the essential part in the following:
# Get the index values and colors from the just created branca-colormap
# NOTE: colors are RGBA-vectors, like "(0.9372549019607843, 0.9529411764705882, 1.0, 1.0)":
for ind_val, c in zip(colormap.index, colormap.colors):
# Create gradient dictionary for heatmap on the fly
r, g, b, a = c
gradient_dict[ind_val] = f"rgba({r},{g},{b},{a})"
The difference to my initial approach is that I passed the color-tuples directly as a tuple with a length of 4, like e.g. (0.9372549019607843, 0.9529411764705882, 1.0, 1.0)
.
The correct form though is like the f-string mentioned above in the loop constructed from the RGBA - values:
f"rgba({r},{g},{b},{a})"