Plot data through Lat & Long - python

Anyone can guide how to can I plot a column value against Lat & Long. The data which I want to plot through python is mentioned below. I have run the code but it isn't working. Kindly guide me on how to do it
Data in CSV File :
Longitude Latitude RSRP
71.676847 29.376015 -89
71.676447 29.376115 -101
71.677847 29.376215 -90
Code :
import pandas as pd
import geopandas as gpd
import matplotlib.pyplot as plt
df = pd.read_csv('C:\\Users\\uwx630237\\BWPMR.csv')
gdf = gpd.GeoDataFrame(df)
Lon = df['Longitude']
Lat = df['Latitude']
RSRP = df['RSRP']
Required Ouput Picture

Without map as background on the plot, you can use df.plot.scatter(). Here is the relevant lines of code that you can try:
# ... previous lines of code
# add a column, named `color`, and set values in it
df.loc[:, 'color'] = 'green' # set all rows -> color=green
df.loc[df['RSRP'] < -100, 'color'] = 'red' # set some rows -> color=red
# plot the data as a scatter plot
df.plot.scatter( x='Longitude' , y='Latitude', s=20, color=df['color'], alpha=0.8 )
The output will look like this:

You can achieve that using folium. Here is a toy example how to add data to a map of San Francisco
import foilum
import folium.plugins
import branca
import branca.colormap as cm
colormap = cm.LinearColormap(colors=['red','lightblue'], index= 90,100],vmin=90,vmax=100)
sanfrancisco_map = folium.Map(location=[37.77, -122.42], zoom_start=12)
lat = list(df.latitude)
lon = list(df.longitude)
RSRP = list(df.RSRP)
for loc, RSRP in zip(zip(lat, lon), RSRP):
folium.Circle(
location=loc,
radius=10,
fill=True,
color=colormap(p),
).add_to(map)
# add incidents to map
sanfran_map.add_child(colormap)

Related

How to add static text in map using Plotly Choropleth Python

I am plotting a map using plotly express and geojson file.I want to show static values on the individual district. Currently those values are visible on hover, but I want the values to be seen all the time even without hovering on it.
This is my code:
import json
import pandas as pd
import numpy as np
import plotly.express as px
import plotly.io as pio
x = json.load(open("./odisha_disticts.geojson","r"))
user_data = []
for i in range(len(x['features'])):
d = x['features'][i]['properties']
d['Females'] = np.random.randint(0,100,1)[0]
user_data.append(d)
df = pd.DataFrame(user_data)
df.head()
ID_2 NAME_2 Females
0 16084 Angul 19
1 16085 Baleshwar 45
2 16086 Baragarh 52
3 16087 Bhadrak 81
4 16088 Bolangir 49
fig = px.choropleth(
df,
locations="ID_2",
featureidkey="properties.ID_2",
geojson=x,
color="Females"
)
fig.update_geos(fitbounds="locations", visible=False)
px.scatter_geo(
df,
geojson=x,
featureidkey="properties.NAME_2",
locations="District",
text = df["District"]
)
fig.show()
The link to required files is HERE
To annotate on a map, use a graph_object to go.Choroplethmapbox with go.Scattermapbox with textmode. As a preparation before creating the graph, we need the latitude and longitude for the annotation, so we use geopandas to read the geojson file and find the center of geometry. A warning is displayed at this point because the loaded geometry uses an inappropriate geodetic system to calculate the center. If you have a latitude and longitude you wish to use for your annotations use it. There are two caveats in creating the map: first, you will need the free Mapbox API token. Get it here. second, in go.Scattemapbox(), the mode is text + marker, but if you use text only, an error will occur. The reason is unknown.
import geopandas as gpd
import pandas as pd
import plotly.graph_objects as go
# read your data
data = pd.read_csv('./data.csv', index_col=0)
# read geojson
x = json.load(open("./odisha_disticts.geojson","r"))
gdf = gpd.read_file('./odisha_disticts.geojson')
gdf['centroid'] = gdf['geometry'].centroid
gdf['lon'] = gdf['centroid'].map(lambda p:p.x)
gdf['lat'] = gdf['centroid'].map(lambda p:p.y)
gdf.head()
ID_2 NAME_2 geometry centroid lon lat
0 16084 Angul POLYGON ((85.38891 21.17916, 85.31440 21.15510... POINT (84.90419 20.98316) 84.904186 20.983160
1 16085 Baleshwar POLYGON ((87.43902 21.76406, 87.47124 21.70760... POINT (86.90547 21.48738) 86.905470 21.487376
2 16086 Baragarh POLYGON ((83.79293 21.56323, 83.84026 21.52344... POINT (83.34884 21.22068) 83.348838 21.220683
3 16087 Bhadrak POLYGON ((86.82882 21.20137, 86.82379 21.13752... POINT (86.61598 20.97818) 86.615981 20.978183
4 16088 Bolangir POLYGON ((83.45259 21.05145, 83.44352 21.01535... POINT (83.16839 20.58812) 83.168393 20.588121
import plotly.express as px
import plotly.graph_objects as go
mapbox_token = open("mapbox_api_key.txt").read()
fig = go.Figure()
fig.add_trace(go.Scattermapbox(lat=gdf['lat'],
lon=gdf['lon'],
mode='text+markers',
textposition='top center',
text = [str(x) for x in data["District"]],
textfont=dict(color='blue')
))
fig.add_trace(go.Choroplethmapbox(geojson=x,
locations=data['id'],
z=data['Females'],
featureidkey="properties.ID_2",
colorscale='Reds',
zmin=0,
zmax=data['Females'].max(),
marker_opacity=0.8,
marker_line_width=0
)
)
fig.update_layout(height=600,
mapbox=dict(
center={"lat": gdf['lat'].mean(), "lon": gdf['lon'].mean()},
accesstoken=mapbox_token,
zoom=5.5,
style="light"
))
fig.show()

Issues Using geoplot.kdeplot with geopandas

Im trying to make a kdeplot using geopandas.
this is my code:
Downloading shape file
URL = "https://data.sfgov.org/api/geospatial/wkhw-cjsf?method=export&format=Shapefile"
response = requests.get(URL)
open('pd_data.zip', 'wb').write(response.content)
with zipfile.ZipFile('./pd_data.zip', 'r') as zip_ref:
zip_ref.extractall('./ShapeFiles')
Making the geopandas data frame
data = train.groupby(['PdDistrict']).count().iloc[:,0]
data = pd.DataFrame({ "district": data.index,
"incidences": data.values})
california_map = str(list(pathlib.Path('./ShapeFiles').glob('*.shp'))[0])
gdf = gdp.read_file(california_map)
gdf = pd.merge(gdf, data, on = 'district')
Note: I didn't include the link to the train set because it's not important for this question(use any data you want)
This is the part that I don't get,
what arguments should I pass to the kdeplot function, like where I pass the shape file and where I pass the data?
ax = gplt.kdeplot(
data, clip=gdf.geometry,
shade=True, cmap='Reds',
projection=gplt.crs.AlbersEqualArea())
gplt.polyplot(boroughs, ax=ax, zorder=1)
had a few challenges setting up an environment where I did not get kernel crashes. Used none wheel versions of shapely and pygeos
a few things covered in documentation kdeplot A basic kdeplot takes pointwise data as input. You did not provide sample for data I'm not sure that it is point wise data. Have simulated point wise data, 100 points within each of the districts in referenced geometry
I have found I cannot use clip and projection parameters together. One or the other not both
shape file is passed to clip
import geopandas as gpd
import pandas as pd
import numpy as np
import geoplot as gplt
import geoplot.crs as gcrs
# setup starting point to match question
url = "https://data.sfgov.org/api/geospatial/wkhw-cjsf?method=export&format=Shapefile"
gdf = gpd.read_file(url)
# generate 100 points in each of the districts
r = np.random.RandomState(42)
N = 5000
data = pd.concat(
[
gpd.GeoSeries(
gpd.points_from_xy(*[r.uniform(*g.bounds[s::2], N) for s in (0, 1)]),
crs=gdf.crs,
).loc[lambda s: s.intersects(g.buffer(-0.003))]
for _, g in gdf["geometry"].iteritems()
]
)
data = (
gpd.GeoDataFrame(geometry=data)
.sjoin(gdf)
.groupby("district")
.sample(100, random_state=42)
.reset_index(drop=True)
)
ax = gplt.kdeplot(
data,
clip=gdf,
fill=True,
cmap="Reds",
# projection=gplt.crs.AlbersEqualArea(),
)
gplt.polyplot(gdf, ax=ax, zorder=1)

How to annotate points in a scatterplot based on a pandas column

Wanted 'Age' as the x-axis, 'Pos' as the y-axis and labels as 'Player' Names. But for some reason, not able to do label the points.
Code:
import numpy as np
import matplotlib.pyplot as plt
import pandas as pd
import adjustText as at
data = pd.read_excel("path to the file")
fig, ax = plt.subplots()
fig.set_size_inches(7,3)
df = pd.DataFrame(data, columns = ['Player', 'Pos', 'Age'])
df.plot.scatter(x='Age',
y='Pos',
c='DarkBlue', xticks=([15,20,25,30,35,40]))
y = df.Player
texts = []
for i, txt in enumerate(y):
plt.text()
at.adjust_text(texts, arrowprops=dict(arrowstyle="simple, head_width=0.25, tail_width=0.05", color='black', lw=0.5, alpha=0.5))
plt.show()
Summary of the data :
df.head()
Player Pos Age
0 Thibaut Courtois GK 28
1 Karim Benzema FW 32
2 Sergio Ramos DF 34
3 Raphael Varane DF 27
4 Luka Modric MF 35
Error :
ConversionError: Failed to convert value(s) to axis units: 'GK'
This is the plot so far; not able to label these points:
EDIT:
This is what I wanted but of all points:
Also, Could anyone help me in re-ordering the labels on the yaxis.
Like, I wanted FW,MF,DF,GK as my order but the plot is in MF,DF,FW,GK.
Thanks.
A similar solution was described here. Essentially, you want to annotate the points in your scatter plot.
I have stripped your code. Note that you need to plot the data with matplotlib (and not with pandas): df = pd.DataFrame(data, columns = ['Player', 'Pos', 'Age']). In this way, you can use the annotation()-method.
import matplotlib.pyplot as plt
import pandas as pd
# build data
data = [
['Thibaut Courtois', 'GK', 28],
['Karim Benzema', 'FW', 32],
['Sergio Ramos','DF', 34],
['Raphael Varane', 'DF', 27],
['Luka Modric', 'MF', 35],
]
# create pandas DataFrame
df = pd.DataFrame(data, columns = ['Player', 'Pos', 'Age'])
# open figure + axis
fig, ax = plt.subplots()
# plot
ax.scatter(x=df['Age'],y=df['Pos'],c='DarkBlue')
# set labels
ax.set_xlabel('Age')
ax.set_ylabel('Pos')
# annotate points in axis
for idx, row in df.iterrows():
ax.annotate(row['Player'], (row['Age'], row['Pos']) )
# force matplotlib to draw the graph
plt.show()
This is what you'll get as output:

Altair choropleth map, color highlight based on line chart selection

I am plotting a choropleth map colored by the field Passenger_0_ and a line chart showing the evolution of Passenger_0_ throughout a day by zone.
I would like to select a line (zone) in the line chart and have it highlighted in the map and vice versa (select a zone in the map and have it highlighted in the line chart).
For now, I am able to change the whole color of the map when selecting the line, but have no clue of how to only change the color of the selected area.
I would appreciate any help.
In order to reproduce the sample you need to download these two files:
output_data.csv
taxi_zones.geojson
Then run this piece of code to get a GeoDataFrame named long_df:
import altair as alt
import pandas as pd
import geopandas as gpd
import json
geo_json_file_loc= './taxi_zones.geojson'
with open(geo_json_file_loc) as json_data:
data = json.load(json_data)
gdf = gpd.GeoDataFrame.from_features((data))
gdf = gdf[gdf['borough']=='Manhattan']
gdf = gdf[['location_id','zone','geometry']]
gdf = gdf.rename(columns={'location_id':'LocationID'})
gdf['LocationID'] = pd.to_numeric(gdf['LocationID'])
output_data = pd.read_csv('./output_data.csv',sep=',')
def load_taxis_data(output_data, shape_data):
df_to_visualize = shape_data.copy()
pickups = output_data.groupby(['hour','dayofweek','LocationID']).sum()
listofdays = pd.unique(output_data['dayofweek'])
for hour in range(24):
for dayofweek in listofdays:
# get pickups for this hour and weekday
p = pd.DataFrame(pickups.loc[(hour, dayofweek)]).reset_index()
# add pickups to the Taxi Zones DataFrame
df_to_visualize = pd.merge(df_to_visualize, p, on="LocationID", how="left").fillna(0)
# rename column as per day and hour
df_to_visualize.rename(columns={"pickups" : "Passenger_%d_%d"%(dayofweek, hour)}, inplace=True)
return df_to_visualize
gdf_merged = load_taxis_data(output_data, gdf)
# drop unwanted days
for hour in range(24):
for dayofweek in [5,6]:
column_to_drop = "Passenger_%d_%d"%(dayofweek, hour)
gdf_merged.drop([column_to_drop], axis=1, inplace=True)
gdf_merged.reset_index(level=0, inplace=True)
long_df = pd.wide_to_long(gdf_merged, ["Passenger_0_"], i='index', j="hour")
long_df = long_df.reset_index()
Once you got long_df this is the code for the plots:
dict_json = json.loads(long_df[long_df['hour']==0].to_json())
colours_obj = alt.Color('properties.Passenger_0_:Q',
scale=alt.Scale(scheme='yelloworangered'),
title = "Pickups")
sel_line_hover = alt.selection_single(on='mouseover', empty='none')
sel_line_col = alt.selection_single()
sel_line_size = alt.selection_single(empty='none')
base = alt.Chart(alt.Data(values=dict_json['features'])).mark_geoshape(
stroke='black',
strokeWidth=1
).encode(
color=alt.condition(sel_line_col, colours_obj, alt.value('lightgray')),
tooltip = ['properties.zone:O',
'properties.Passenger_0_:Q']
).properties(
width=350,
height=750,
).add_selection(
sel_line_col
)
line = alt.Chart(long_df).mark_line().encode(
x='hour',
y='Passenger_0_',
color=alt.condition(sel_line_hover|sel_line_col, 'zone', alt.value('lightgray')),
size=alt.condition(sel_line_hover|sel_line_size, alt.value(4),alt.value(1)),
tooltip = ['zone:O']
).properties(
width=250,
height=750,
).add_selection(
sel_line_hover,sel_line_col,sel_line_size
)
base | line
And this is what the plot does:
Thank you in advance for your help!
Here is a general example of how to achieve two-way interactivity in Altair, using data from the sample repos only. The key is to set the feature that should be filtered by the selection even via fields parameter when creating the selection. Then you add this selection and the corresponding condition to the same encoding of both the plots.
import altair as alt
from vega_datasets import data
state_pop = data.population_engineers_hurricanes()[['state', 'id', 'population']]
state_map = alt.topo_feature(data.us_10m.url, 'states')
click = alt.selection_multi(fields=['state'])
choropleth = (alt.Chart(state_map).mark_geoshape().transform_lookup(
lookup='id',
from_=alt.LookupData(state_pop, 'id', ['population', 'state']))
.encode(
color='population:Q',
opacity=alt.condition(click, alt.value(1), alt.value(0.2)),
tooltip=['state:N', 'population:Q'])
.add_selection(click)
.project(type='albersUsa'))
bars = (
alt.Chart(
state_pop.nlargest(15, 'population'),
title='Top 15 states by population').mark_bar().encode(
x='population',
opacity=alt.condition(click, alt.value(1), alt.value(0.2)),
color='population',
y=alt.Y('state', sort='x'))
.add_selection(click))
choropleth & bars

Unsure how to use colormap with Folium marker plot

I have a dataframe with latitude, longitude, and power percentage. I want to do something very simple but not sure how: apply a colormap to color the data points based on their percentage. So 90% is red and 100% is blue. I have created both a successful map and colormap, but not sure how to proceed next.
import folium
import pandas as pd
import folium.plugins
import branca
import branca.colormap as cm
data = [
[33.823400, -118.12194, 99.23],
[33.823500, -118.12294, 95.23],
[33.823600, -118.12394, 91.23],
[33.823700, -118.12494, 90.00]
]
df = pd.DataFrame(data, columns=['latitude','longitude','power'])
x_start = (df['latitude'].max() + df['latitude'].min()) / 2
y_start = (df['longitude'].max() + df['longitude'].min()) / 2
start_coord = (x_start, y_start)
map = folium.Map(location=start_coord, zoom_start=12)
lat = list(df.latitude)
lon = list(df.longitude)
for loc in zip(lat, lon):
folium.Circle(
location=loc,
radius=10,
#fill=True,
#color='blue',
#fill_opacity=0.7
).add_to(map)
display(map)
colormap = cm.LinearColormap(colors=['red','lightblue'], index=[90,100],vmin=90,vmax=100)
colormap
I'm in a rush, but this is how I've done it in the past. Create the CM and then call it like so colormap(.9)
import folium
import pandas as pd
import folium.plugins
import branca
import branca.colormap as cm
data = [
[33.823400, -118.12194, 99.23],
[33.823500, -118.12294, 95.23],
[33.823600, -118.12394, 91.23],
[33.823700, -118.12494, 90.00]
]
df = pd.DataFrame(data, columns=['latitude','longitude','power'])
x_start = (df['latitude'].max() + df['latitude'].min()) / 2
y_start = (df['longitude'].max() + df['longitude'].min()) / 2
start_coord = (x_start, y_start)
colormap = cm.LinearColormap(colors=['red','lightblue'], index=[90,100],vmin=90,vmax=100)
map = folium.Map(location=start_coord, zoom_start=12)
lat = list(df.latitude)
lon = list(df.longitude)
pow = list(df.power)
for loc, p in zip(zip(lat, lon), pow):
folium.Circle(
location=loc,
radius=10,
fill=True,
color=colormap(p),
#fill_opacity=0.7
).add_to(map)
map.add_child(colormap)
display(map)

Categories