Reputation: 326
I am trying to create a map with plotly.express that displays values are bubbles (circles).
The values currently range from 16000 to 21500. I have got everything up and running, the bubbles are displayed in different colors, however, they are more or less all of the same size.
What I would like to have is the smallest value to be displayed with a small bubble and the largest value with a large bubble and the other values in between.
This is how my data frame looks like:
country average long lat
0 Baden-Württemberg 19166.381092 9.179330 48.781956
1 Bayern 18786.556728 11.572199 48.137859
2 Berlin 21463.044514 13.387224 52.533707
3 Brandenburg 19622.567766 13.070526 52.405476
4 Bremen 16197.013903 8.805129 53.081386
5 Hamburg 18426.436184 10.001104 53.554158
and this is the way how I display it:
fig = px.scatter_mapbox(all_data, lat="lat", lon="long", hover_name="country", hover_data=["country", "average"],
color="average",
size="average", color_continuous_scale=px.colors.sequential.matter, size_max=20,
zoom=5, height=1000, mapbox_style="open-street-map")
fig.update_layout(margin={"r":0,"t":0,"l":0,"b":0})
fig.show()
And this is how it looks like: open street map with bubbles
How can I influence the size of the bubbles so that a smaller value has a small diameter and and larger value has a large diameter?
I tried to play with the size_max-value, but all the bubbles will still have the same size, just all of them larger or smaller.
Upvotes: 4
Views: 13858
Reputation: 326
I have found out, that the size-Parameter can take a list of values that reflect the scale. This will not influence the scale that is drawn right of the map.
So I did this:
# doing a little bit of math here to calculate a scale to reflect the difference between
# the minimum and the maximum of the average prices (could probably be done much more elegant,
# but this does the job)
#
# first, calculate a ratio between max and min and divide it to have 16 steps
all_data_diffq = (all_data["mean"].max() - all_data["mean"].min()) / 16
# calculate the scale value by subtracting the minium value from the average price, divide
# that by the ratio which will give the scale a value between 0...15 and add 1 to it so that
# the scale values start at 1 (to be visible on the map)
# add the according scale to each row
# the scale column will then be used for size=... parameter in the scatter_mapbox call below
all_data["scale"] = (all_data["mean"] - all_data["mean"].min()) / all_data_diffq + 1
My dataframe looks like this now:
country mean long lat scale
0 Baden-Württemberg 19166.381092 9.179330 48.781956 10.021952
1 Bayern 18786.556728 11.572199 48.137859 8.867916
2 Berlin 21463.044514 13.387224 52.533707 17.000000
3 Brandenburg 19622.567766 13.070526 52.405476 11.408003
4 Bremen 16197.013903 8.805129 53.081386 1.000000
5 Hamburg 18426.436184 10.001104 53.554158 7.773747
And the call of scatter_mapbox() now uses the "scale" column for the size-parameter:
fig = px.scatter_mapbox(all_data, lat="lat", lon="long", hover_name="country", hover_data=["country", "mean"],
color="mean",
size=all_data["scale"], color_continuous_scale=px.colors.sequential.Rainbow,
size_max=50, zoom=5, height=1000, mapbox_style="open-street-map")
fig.update_layout(margin={"r":0,"t":0,"l":0,"b":0})
fig.show()
Now the result looks better:
applied scale the to the size-parameter
Upvotes: 3
Reputation: 35205
Your code is correct. The size was not noticeable due to the similarity of the data subject to the size. I deliberately modified Bremen's data to a larger size to draw the graph. The other fix is to change the 'size_max'. I also changed the color of the bubble to a color that does not blend with the map.
import pandas as pd
import numpy as np
import io
data = '''
country average long lat
0 Baden-Württemberg 19166.381092 9.179330 48.781956
1 Bayern 18786.556728 11.572199 48.137859
2 Berlin 21463.044514 13.387224 52.533707
3 Brandenburg 19622.567766 13.070526 52.405476
4 Bremen 46197.013903 8.805129 53.081386 # average value update
5 Hamburg 18426.436184 10.001104 53.554158
'''
all_data = pd.read_csv(io.StringIO(data), sep='\s+')
import plotly.express as px
fig = px.scatter_mapbox(all_data, lat="lat", lon="long", hover_name="country", hover_data=["country", "average"],
color="average",
size="average", color_continuous_scale=px.colors.sequential.Rainbow, size_max=40,
zoom=5, height=1000, mapbox_style="open-street-map")
fig.update_layout(margin={"r":0,"t":0,"l":0,"b":0})
fig.show()
Upvotes: 2