I'm trying to create a heatmap for countries. I've created a custom geojson, which is working fine, by it's own.
Unfortunately, when I link to the dataframe where the amount are displayed, only part of the heat map are rendered, excluding some areas.
Why is that?
Thanks a lot
data and code available here
You have missed one important parameter: featureidkey This is the join between the geometry and data frame (location)
Have also simplified your aggregate to removed need for reset_index()
full code
import geopandas as gpd
import pandas as pd
import plotly.express as px
gdf = gpd.read_file(
"https://raw.githubusercontent.com/vincenzojrs/test/main/map-2.geojson"
)
sellers = pd.read_csv(
"https://raw.githubusercontent.com/vincenzojrs/test/main/sellers.csv"
)
sellersxcity = sellers.groupby(["id_ac"], as_index=False).agg({"num_ord_sell": "sum"})
fig = px.choropleth_mapbox(
sellersxcity,
geojson=gdf,
featureidkey="properties.ID_1",
locations="id_ac",
color="num_ord_sell",
color_continuous_scale="Viridis",
mapbox_style="carto-positron",
zoom=3,
center={"lat": 40.4999, "lon": -3.673},
labels={"num_ord_sell": "Count for Orders"},
)
fig.update_layout(margin={"r": 0, "t": 0, "l": 0, "b": 0})
Related
I tried to create several maps and saved as png files. In cycle I got all mapes per year. I want to add which year on the map, and I tried title=i and fig.update_layout(title_text=i, title_x=0.5), but it does not work.
import plotly.express as px
import pandas as pd
year = [1980,1981,1983]
lat = [60.572959, 60.321403, 56.990280]
lon = [40.572759, 41.321203, 36.990299]
dataframe = pd.DataFrame(list(zip(year,lat,lon)),
columns =['year', 'lat', 'lon'])
for idx, i in enumerate(sorted(dataframe['year'].unique())):
#for x in range(1980,2022):
sp = sp1[sp1['year']==i]
fig = px.scatter_mapbox(dataframe, lat='lat', lon="lon",
color_discrete_sequence=["fuchsia"], zoom=2, height=400, opacity=0.3, title = i)
fig.update_layout(mapbox_style="open-street-map")
fig.update_layout(margin={"r":0,"t":0,"l":0,"b":0})
fig.update_layout(title_text=i, title_x=0.5)
fig.write_image("all/plot{idx}.png".format(idx=idx))
I put the picture of one map as example. I want to add year for every map in any place.
Use the annotations attribute of the previously created layout object in the update_layout method to add text - specified by the x and y coordinates.
fig.update_layout(annotations=[
dict(text=i, x=0.5, y=0.5, font_size=15, showarrow=False)
])
Play around with the x and y coordinates to find the proper position you want to place your text at.
All you should do is to specify a space for the title by customizing the margin:
import plotly.express as px
import pandas as pd
df = pd.read_csv(
"https://raw.githubusercontent.com/plotly/datasets/master/2011_february_us_airport_traffic.csv"
)
fig = px.scatter_mapbox(df, lat="lat", lon="long", size="cnt", zoom=3)
fig.update_layout(mapbox_style="open-street-map")
fig.update_layout(
title_x=0.5,
title_y=0.95,
title_text="2011_february_us_airport_traffic",
margin={"l": 0, "r": 0, "b": 0, "t": 80}
)
fig.show()
Output:
I want to plot a bar chart on a map created with plotly, similar to the QGIS plot here. Ideally, the bar chart would be stacked and grouped instead of just grouped. So far, I only found examples for pie charts on plotly maps, for instance here.
with plotly mapbox you can add layers
with plotly you can generate images from figures
using above two facts you can add URI encoded images to a mapbox figure
you have not provided any sample geometry or data. Have used a subset geopandas sample geometry plus generated random data for each country (separate graph)
the real key to this solution is layer-coordinates
get centroid of a country
add a buffer around this and get envelope (bounding rectangle)
arrange co-ordinates of envelope to meet requirements stated in link
import geopandas as gpd
import plotly.express as px
import numpy as np
import base64, io
# create an encocded image of graph...
# change to generate graph you want
def b64image(vals=np.random.randint(1, 25, 5)):
fig = px.bar(
pd.DataFrame({"y": vals}).pipe(
lambda d: d.assign(category=d.index.astype(str))
),
y="y",
color="category",
).update_layout(
showlegend=False,
xaxis_visible=False,
yaxis_visible=False,
bargap=0,
margin={"l": 0, "r": 0, "t": 0, "b": 0},
autosize=False,
height=100,
width=100,
paper_bgcolor="rgba(0,0,0,0)",
plot_bgcolor="rgba(0,0,0,0)",
)
b = io.BytesIO(fig.to_image(format="png"))
b64 = base64.b64encode(b.getvalue())
return "data:image/png;base64," + b64.decode("utf-8"), fig
# get some geometry
world = gpd.read_file(gpd.datasets.get_path("naturalearth_lowres"))
# let's just work with a bounded version of europe
eur = world.loc[
lambda d: d["continent"].eq("Europe")
& ~d["iso_a3"].isin(["RUS", "NOR", "FRA", "ISL"])
]
px.choropleth_mapbox(
eur,
geojson=eur.__geo_interface__,
locations="iso_a3",
featureidkey="properties.iso_a3",
color_discrete_sequence=["lightgrey"],
).update_layout(
margin={"l": 0, "r": 0, "t": 0, "b": 0},
showlegend=False,
mapbox_style="carto-positron",
mapbox_center={
"lon": eur.unary_union.centroid.x,
"lat": eur.unary_union.centroid.y,
},
mapbox_zoom=3,
# add a plotly graph per country...
mapbox_layers=[
{
"sourcetype": "image",
# no data provided, use random values for each country
"source": b64image(vals=np.random.randint(1, 25, 5))[0],
# https://plotly.com/python/reference/layout/mapbox/#layout-mapbox-layers-items-layer-coordinates
# a few hops to get 4 cordinate pairs to meet mapbox requirement
"coordinates": [
list(p) for p in r.geometry.centroid.buffer(1.1).envelope.exterior.coords
][0:-1][::-1],
}
for i, r in eur.iterrows()
],
)
output
I have a dataframe with latitude and longitude values. I was able to plot the points on a global map however my requirement is to achieve something like this:
Code for current map:
import plotly.express as px
fig = px.scatter_geo(data,lat=data['Y'],lon=data['X'])
fig.update_layout()
fig.show()
Current Map:
The data is from NICE, France. I can use any library or package but my data is only limited to lat and lon columns. I will be putting in the color on the map based on another column but for now just the map itself with the points and outline is needed. How do I achieve this?
Thanks
Data Sample:
[[ 7.07406569, 43.63045404],
[ 7.06488181, 43.61782587],
[ 6.943076 , 43.653562 ],
[ 6.927238 , 43.65362208],
[ 7.092407 , 43.600197 ],
[ 7.099427 , 43.632552 ]]
Ok, so let's go through it step by step.
First, get the geojson for the area. We find that courtesy of https://github.com/gregoiredavid/france-geojson. We get the Alpes Maritimes area, we isolate Nice area from it (Nice-1 to Nice-9), and we generate some dummy data for it, in a new dataframe. We merge dataframes on name column, and we plot it:
import geopandas as gpd
import plotly.express as px
import json
with open('cantons-06-alpes-maritimes.geojson') as f:
data = json.load(f)
alpes_maritimes_data = gpd.GeoDataFrame.from_features(data['features'])
nice_df = alpes_maritimes_data[14:22]
df_list = [('Nice-1', 72), ('Nice-2', 112), ('Nice-3', 44), ('Nice-5', 2345), ('Nice-6', 99)]
data_df = pd.DataFrame(df_list, columns = ['Name', 'Data'])
merged_df = nice_df.merge(data_df, how='left', left_on='nom', right_on='Name').set_index("Name").fillna(0)
fig = px.choropleth(merged_df,
geojson=merged_df.geometry,
locations=merged_df.index, color="Data",
range_color=(merged_df["Data"].min(), merged_df["Data"].max()),
title = 'Nice, France'
)
fig.update_geos(fitbounds="locations", visible=False)
fig.update_layout(margin={"r":0,"t":50,"l":0,"b":0})
fig.show()
And we get our choropleth map:
I want to create an interactive map that shows the evolution of a variable (number of bikes) on different points of a city.
Why not by using plotly.
I would like to do something like this : https://amaral.northwestern.edu/blog/step-step-how-plot-map-slider-represent-time-evolu with a slider.
However, I don't achieve to reproduce it with focusing on a city, I can't choose a scope more precise than "europe".
Do you know how to do it with a zoom ?
you have not provided any code or sample data. Hence have used this http://api.citybik.es/v2/ https://github.com/eskerda/pybikes project to source some bike data
data is just latest, so build up data in a pickle file for evolution
simple case of using Plotly Express and animation_frame argument
data sources
import requests
import pandas as pd
from pathlib import Path
import plotly.express as px
# avalaible data sources...
pd.json_normalize(
requests.get("http://api.citybik.es/v2/networks").json()["networks"]
).loc[lambda d: d["location.city"].eq("London")]
bike stand sourcing and plotting
df = pd.json_normalize(
requests.get("http://api.citybik.es/v2/networks/santander-cycles").json()[
"network"
]["stations"]
)
# build up some data over time
df["timestamp"] = pd.to_datetime(df["timestamp"]).round("15min")
f = Path.cwd().joinpath("bikes.pickle")
if not f.exists():
df.to_pickle(f)
else:
df = pd.concat([pd.read_pickle(f), df])
df = df.groupby(["timestamp","id"], as_index=False).first()
df.to_pickle(f)
# now just plot it on a map with evolution by time
df["ts_str"] = df["timestamp"].dt.strftime("%d-%b %H:%M")
px.scatter_mapbox(
df,
lat="latitude",
lon="longitude",
size="free_bikes",
hover_data=["name"],
animation_frame="ts_str",
).update_layout(
mapbox={"style": "carto-positron", "zoom":11}, margin={"l": 0, "r": 0, "t": 0, "b": 0}
)
I am trying to use custom hexa codes for each bar in a plotly chart but I am not able to work this out.
Could someone please help me.
Below is the code I a working with
#Defining Custom Colors
colours = {'Base_Models': '#0C3B5D',
'Standard_scaled_scores': '#3EC1CD',
'Min_Max_scaled_scores': '#EF3A4C',
'Scaling & feature selection_scores': '#FCB94D'}
import plotly.express as px
fig = px.bar(compareModels_aft_Cleansing, x="Base_Models", y=["Base_Models_Scores",
"Standard_scaled_scores", "Min_Max_scaled_scores",
"Scaling & feature selection_scores"],
title="Training Scores", barmode='group', text = 'value',
hover_name="Base_Models",
hover_data={'Base_Models':False}, # remove species from hover data
color = colours)
you have not provided sample data so I have synthesized
your colours map as I understand your dataframe is incorrect. You are plotting Base_Models_Scores as a bar not Base_Models, this is the x-axis
the parameter you require is color_discrete_map to achieve your requirement
import pandas as pd
import numpy as np
# Defining Custom Colors
colours = {
"Base_Models_Scores": "#0C3B5D",
"Standard_scaled_scores": "#3EC1CD",
"Min_Max_scaled_scores": "#EF3A4C",
"Scaling & feature selection_scores": "#FCB94D",
}
# generate sample data...
compareModels_aft_Cleansing = pd.DataFrame(
{
**{"Base_Models": colours.keys()},
**{
c: np.random.randint(1, 4, len(colours.keys()))
for c in colours.keys()
},
}
)
import plotly.express as px
fig = px.bar(
compareModels_aft_Cleansing,
x="Base_Models",
y=[
"Base_Models_Scores",
"Standard_scaled_scores",
"Min_Max_scaled_scores",
"Scaling & feature selection_scores",
],
title="Training Scores",
barmode="group",
text="value",
hover_name="Base_Models",
hover_data={"Base_Models": False}, # remove species from hover data
color_discrete_map=colours,
)
fig