Folium Heatmap with color bar Values - python

In my project I receive a DataFrame with scores for cities in the US. I can plot the HeatMap using Folium however I would like to add a colorbar to showcase the numerical values of these scores, based on the color of the HeatMap. Is there a way to do it?.
My code so far
cities = pd.read_csv ('../datasets/us.csv'))
cord = cities [["latitude","longitude","score"]]
#create map
base_map = folium.Map(
width = "100%",
height = "100%",
location = [-15.788497,-47.879873],
zoom_start = 4
)
base_map = base_map.add_child(plugins.HeatMap(cord,radius = 20, min_opacity = 0.1))

Related

Using a loop to plot labels on a scatter plot based on their value

Hi I'm new to python and would like to plot the names of the footballers on my scatterplot as labels if their Goals or npxG are greater than the average values i have calculated.
I wondered whether I could use a for/while loop to go through the data and plot the relevant players names?
I've struggled to figure out the most efficient way for this to be done.
Please see the scatter plot and code below for additional context. Any help would be greatly appreciated, Thanks.
df = pd.read_csv('C:/Users/alexo/Documents/Data/football data/shooting_top5_leagues_21_22.csv',encoding = 'ISO-8859-1')
striker_df = df.loc[(df['Pos']=='FW') & (df['90s']>= 15)]
sns.set_style('darkgrid')
sns.set(rc = {'figure.figsize':(15,8)})
graph = sns.scatterplot(striker_df.Gls,striker_df.npxG_p90,hue=striker_df.League,size=striker_df.npxG_pSh,edgecolor = 'black')
# averageline x axis
graph.axvline(9.751677852348994,c='grey',ls='--')
# average line yaxis
graph.axhline(0.34438111920973147,c='grey',ls='--')
#adding label names for specific players
#title
plt.title('Best Strikers across Europes Top 5 leagues 21/22',size=17,c='black')
# add credits
Notes = 'By Alex Orlandini'
CREDIT_1 = "data: statsbomb via fbref"
graph.text(
36, 0.1, f"{Notes}\n{CREDIT_1}", size=10,
color="#000000",
ha="right");
enter image description here
Yes, you can loop through specific players and add the arrow and text.
Just a matter of getting the x, y coordinate of the data point, then deciding where to place the label. I had to pull my own data since you didn't share yours.
I would also avoid hard coding that average. I'd have that as a calculated variable.
import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns
#df = pd.read_csv('C:/Users/alexo/Documents/Data/football data/shooting_top5_leagues_21_22.csv',encoding = 'ISO-8859-1')
df = pd.read_html('https://fbref.com/en/comps/Big5/shooting/players/Big-5-European-Leagues-Stats', header=1)[0]
df = df[df['Rk'].ne('Rk')]
df['npxG'] = df['npxG'].astype(float)
df['90s'] = df['90s'].astype(float)
df['npxG/Sh'] = df['npxG/Sh'].astype(float)
df['Gls'] = df['Gls'].astype(int)
df['npxG_p90'] = df['npxG'] / df['90s']
df['League'] = df['Comp'].str.split(' ',1, expand=True)[1]
df = df.rename(columns={'npxG/Sh':'npxG_pSh'})
striker_df = df.loc[(df['Pos']=='FW') & (df['90s']>= 15)]
sns.set_style('darkgrid')
sns.set(rc = {'figure.figsize':(15,8)})
x_axis_column = 'Gls'
y_axis_column = 'npxG_p90'
graph = sns.scatterplot(x = striker_df[x_axis_column],
y = striker_df[y_axis_column],
hue = striker_df.League,
size = striker_df.npxG_pSh,
edgecolor = 'black')
# averageline x axis
avgX = striker_df[x_axis_column].mean()
graph.axvline(avgX, c='grey', ls='--')
# average line yaxis
avgY = striker_df[y_axis_column].mean()
graph.axhline(avgY, c='grey', ls='--')
xOffset = (striker_df[x_axis_column].max() - striker_df[x_axis_column].min()) *.10
yOffset = (striker_df[y_axis_column].max() - striker_df[y_axis_column].min()) *.10
#adding label names for specific players
for player in ['Robert Lewandowski', 'Kylian Mbappé', 'Patrik Schick', 'Arnaut Groeneveld']:
# Label coordinate, Custom arrow
x = striker_df[striker_df['Player'] == player].iloc[0][x_axis_column]
y = striker_df[striker_df['Player'] == player].iloc[0][y_axis_column]
plt.annotate(player, xy=(x, y),xytext=(x + xOffset, y + yOffset) ,
horizontalalignment="center",
arrowprops=dict(arrowstyle='->', lw=2, color='black')
)
#title
plt.title('Best Strikers across Europes Top 5 leagues 21/22',size=17,c='black')
# add credits
Notes = 'By Alex Orlandini'
CREDIT_1 = "data: statsbomb via fbref"
graph.text(
36, 0.1, f"{Notes}\n{CREDIT_1}", size=10,
color="#000000",
ha="right");
Output:
Or you can iterate through a dataframe:
#adding label names for specific players
striker_df['calc'] = striker_df[x_axis_column] + striker_df[y_axis_column]
striker_df = striker_df.sort_values('calc', ascending = False)
top_players = striker_df.head(8)
for idx, row in top_players.iterrows():
# Label coordinate, Custom arrow
player = row['Player']
x = row[x_axis_column]
y = row[y_axis_column]
plt.annotate(player, xy=(x, y),xytext=(x + xOffset, y) ,
horizontalalignment="center",
arrowprops=dict(arrowstyle='->', lw=2, color='black')
)
To get something like this:

Adding points to pyplot choropeth map

I have created a choropleth map in python with pyplot on US census data. Now I want to add points to this map denoting the location of towns using longitude and latitude. My code below successfully renders the choropleth but not the points on top
fig1 = px.choropleth(population, locations=population['StateAbbr'], locationmode='USA-states',
color='per1910',color_continuous_scale='inferno',
range_color=(0, .15),scope='usa',labels={'StateAbbr':'per1910'},hover_name='StateAbbr',)
go.Figure(data=go.Scattergeo(
lon = champs['Lon'],
lat = champs['Lat'],
text = champs['School'],
mode = 'markers',
marker_color = 'blue',
))
fig1.update_layout(title_text = 'Census: 1910 Championships: 1872-1915')
fig1.show()

How can I annotate text in Basemap using the exact coordinates of the location in Python?

I have created a Basemap of Asia using following lines of code. The projection used is "marcator". The region I want to show in this basemap is Chitwan, Nepal. The coordinates is also provided.
from mpl_toolkits.basemap import Basemap
import matplotlib.pyplot as plt
chitwan = (27.618556599999998, 84.45385600798173)
fig = plt.figure()
ax = fig.add_axes([0.5, 0.5, 2, 2]) #left, bottom, width, height
m = Basemap(
llcrnrlon = 30,
llcrnrlat = 0,
urcrnrlon = 120,
urcrnrlat = 60,
projection = "merc",
resolution = "l"
)
m.plot(chitwan[1], chitwan[0],
latlon = True,
marker = "s",
color = "blue",
markersize = 20)
m.drawcoastlines()
m.fillcontinents()
m.drawcountries()
m.drawstates()
plt.annotate(text = "Chitwan, Nepal", xy = chitwan)
plt.show()
I am able to add a blue square marker in Chitwan, Nepal using
m.plot(chitwan[1], chitwan[0],
latlon = True,
marker = "s",
color = "blue",
markersize = 40)
Passing latlon = True allows me to draw the marker using the coordinates of the place directly.
However, I also want to annotate "Chitwan, Nepal" as a text in the same location.
I tried plt.annotate(text = "Chitwan, Nepal", xy = chitwan). However, this plots the text on the lower left corner of the Basemap as shown below.
I think this should be because the latitude and longitude coordinates of the text is not projected to that of the Basemap. So how can I project the coordinates of my location such that the text is also inserted in the same location as the marker? Is it possible to do this by passing the exact coordinates of the place directly and passing an argument similar to latlon = True for the marker?
Ok. I figured out the way for this myself.
I need to use:
x, y = m(chitwan[1], chitwan[0])
The x and y are projected to the map location with longitude and latitude of chitwan respectively.
And then I annotated the text as follows:
ax.annotate(text = "Chitwan, Nepal",
xy = (x+5,y+5),
)
I get the resulting plot as shown:

How do you plot a limited number of bars in pandas or seaborn?

I have a huge dataset with hundreds of cities. I want to make a bar chart with just the 50 most occurring cities.
Here is what I have so far:
base_color = sb.color_palette()[0]
cat_order = planes_df['OriginCityName'].value_counts().index
plt.figure(figsize = [11, 5])
sb.countplot(data = planes_df, x = 'OriginCityName', color = base_color, order = cat_order)
plt.title('# of planes that takeoff from the origin state')
plt.xlabel('Origin States')
plt.ylabel('Number of Planes')
plt.xticks(rotation = 90);
This plots hundreds of cities. How can I just plot the 50 most frequest cities?
I know there must be a limiter....
You could take the .head() after sorting using .sort_values() and assign that to cat_order:
planes_df['OriginCityName'].value_counts().sort_values().head(50).index

Using Bokeh to plot lat/long points with varying radii (varying size) and varying color based on values

I have a code that produces a map of the united states with points at specified lat longs coordinates. Each of these points is tagged with a value that I want to use to indicate how large the point should be and what color the point should be. The code is below:
points = pd.read_csv(f)
lat = []
lon = []
heat = []
const = []
for i in range(points.shape[0]):
lat.append(points.iat[i,0])
lon.append(points.iat[i,1])
heat.append(points.iat[i,2])
const.append(points.iat[i,3])
source = ColumnDataSource(
data = dict(
lat = lat,
lon = lon,
radius = heat,
constr = const,
)
)
TOOLS = 'box_zoom,wheel_zoom,hover'
state_xs = [states[code]["lons"] for code in states]
state_ys = [states[code]["lats"] for code in states]
p = figure(title="Bound Portfolio", toolbar_location="left",
plot_width=1100, plot_height=700, tools = TOOLS)
p.patches(state_xs, state_ys, fill_alpha=0.3, fill_color = "orange",
line_color="#884444", line_width=2, line_alpha=0.3)
circle = Circle(x="lon", y="lat", size=4.5, fill_color="blue", fill_alpha=0.5, line_color=None)
#circle = Circle(x="lon", y="lat", size=4.5, fill_color="blue", fill_alpha=0.5, line_color=None)
p.add_glyph(source, circle)
lat, lon, heat, and const are lists that I have created by reading the rows of a pandas dataframe. I want the values of heat (1-10) to be the radius of the point in question. I want each unique value in const to map to a unique color for the point in question. I have not been able to figure out how to make this code work. I have tried putting in many variations for the size of circle and it has not worked... the same applies for the color.
Here is an example with unique alpha, color and size.
Key is to store values in a columndatasource then pass this as an argument into a figure method - i.e. .circle("xname", "yname", source=source)
from bokeh.io import show
from bokeh.plotting import figure, ColumnDataSource
lat = [0,1,2,3]
lon = [10,20,30,40]
radius = [1,2,3,4]
constr = [100,200,300,400]
colors= ['#014636', '#016c59','#02818a', '#3690c0']
alpha=[0.8,0.1,0.3,0.5]
source = ColumnDataSource(
data = dict(
lat = lat,
lon = lon,
radius = radius,
constr = constr,
colors=colors,
alpha=alpha
)
)
p = figure(title="Bound Portfolio",
plot_width=1100, plot_height=700)
p.circle("lon","lat",source=source, fill_alpha="alpha", fill_color = "colors",
line_color="colors", line_width=2, line_alpha=0.3,radius="radius")

Categories