I have a geodataframe with Multistring Geometry. I wanted to plot an interactive map, on which when I click on each line, the name and id would appear! I can see that mouse form would change but nothing will appear. I also tried to define the names as labels but it did not work!
Ex_centreLine_map= folium.Map(location = [43.7180, -79.3762], zoom_start=12)
folium.Choropleth(
centreline_gdf[centreline_gdf.geometry.length> 0.00001],
line_weight=3,
line_color='blue',
popup=centreline_gdf[['lf_name', 'lfn_id']]).add_to(Ex_centreLine_map)
Ex_centreLine_map
you have not provided any sample data, so I have used some road data to make a MWE
you can do native folium however it's simpler to use geopandas explore()
for native folium you can to use folium.GeoJson()
import geopandas as gpd
import pandas as pd
import shapely.wkt
import io
df = pd.read_csv(io.StringIO("""ref;lanes;highway;maxspeed;length;name;geometry
A3015;2;primary;40 mph;40.68;Rydon Lane;MULTILINESTRING ((-3.4851169 50.70864409999999, -3.4849879 50.7090007), (-3.4857269 50.70693379999999, -3.4853034 50.7081574), (-3.488620899999999 50.70365289999999, -3.4857269 50.70693379999999), (-3.4853034 50.7081574, -3.4851434 50.70856839999999), (-3.4851434 50.70856839999999, -3.4851169 50.70864409999999))
A379;3;primary;50 mph;177.963;Rydon Lane;MULTILINESTRING ((-3.4763853 50.70886769999999, -3.4786112 50.70811229999999), (-3.4746017 50.70944449999999, -3.4763853 50.70886769999999), (-3.470350900000001 50.71041779999999, -3.471219399999999 50.71028909999998), (-3.465049699999999 50.712158, -3.470350900000001 50.71041779999999), (-3.481215600000001 50.70762499999999, -3.4813909 50.70760109999999), (-3.4934747 50.70059599999998, -3.4930204 50.7007898), (-3.4930204 50.7007898, -3.4930048 50.7008015), (-3.4930048 50.7008015, -3.4919513 50.70168349999999), (-3.4919513 50.70168349999999, -3.49137 50.70213669999998), (-3.49137 50.70213669999998, -3.4911565 50.7023015), (-3.4911565 50.7023015, -3.4909108 50.70246919999999), (-3.4909108 50.70246919999999, -3.4902349 50.70291189999999), (-3.4902349 50.70291189999999, -3.4897693 50.70314579999999), (-3.4805021 50.7077218, -3.4806265 50.70770150000001), (-3.488620899999999 50.70365289999999, -3.4888806 50.70353719999999), (-3.4897693 50.70314579999999, -3.489176800000001 50.70340539999999), (-3.489176800000001 50.70340539999999, -3.4888806 50.70353719999999), (-3.4865751 50.70487679999999, -3.4882604 50.70375799999999), (-3.479841700000001 50.70784459999999, -3.4805021 50.7077218), (-3.4882604 50.70375799999999, -3.488620899999999 50.70365289999999), (-3.4806265 50.70770150000001, -3.481215600000001 50.70762499999999), (-3.4717096 50.71021009999998, -3.4746017 50.70944449999999), (-3.4786112 50.70811229999999, -3.479841700000001 50.70784459999999), (-3.471219399999999 50.71028909999998, -3.4717096 50.71021009999998))"""),
sep=";")
gdf = gpd.GeoDataFrame(df, geometry=df["geometry"].apply(shapely.wkt.loads), crs="epsg:4326")
gdf.explore(style_kwds={"weight":10})
native folium
import folium
m = folium.Map(
location=[sum(gdf.total_bounds[[1, 3]]) / 2, sum(gdf.total_bounds[[0, 2]]) / 2],
zoom_start=12,
)
def style_fn(x):
return {"color":"blue", "weight":3}
folium.GeoJson(
gdf,
style_function=style_fn,
popup=folium.GeoJsonPopup(gdf.drop(columns=["geometry"]).columns.tolist()),
tooltip=folium.GeoJsonTooltip(["ref"]),
).add_to(m)
m
Related
I have a geopandas DataFrame with bounds geometry.
import pandas as pd
import geopandas as gpd
gdf = gpd.GeoDataFrame({
'id': [0, 1],
'b': [((40.6494140625, -86.7919921875), (40.69335937...)),
((39.55078125, -93.8232421875), (39.5947265625...))]
})
gdf['b'][0]
Bounds(sw=SouthWest(lat=32.8271484375, lon=-96.8115234375), ne=NorthEast(lat=32.87109375, lon=-96.767578125))
print(type(gdf['b'][0]))
<class 'geolib.geohash.Bounds'>
How do I turn Bounds into Polygon geometry type? Like,
Polygon((40.6494140625, -86.7919921875), (40.69335937...))
Suppose you have:-
# bound1 = The geohash.Bounds object.
you can proceed with:-
from shapely.geometry import box
bounds_pgon = box(bounds1.sw.lon, bounds1.sw.lat,
bounds1.ne.lon, bounds1.ne.lat)
# Check the result
bounds_pgon.wkt
the output will be similar to this:-
'POLYGON ((-27.9986 70.2987, -27.9986 70.3001, -28.0000 70.3001, -28.0000 70.2987, -27.9986 70.2987))'
This is really the same answer that #swatchi has provided.
Shape of the geometry is defined by the precision of the hash. See reference: geohash
import geolib.geohash
import shapely.geometry
import geopandas as gpd
import pandas as pd
# Bounds(sw=SouthWest(lat=32.8271484375, lon=-96.8115234375), ne=NorthEast(lat=32.87109375, lon=-96.767578125))
# regenerate the referenced geohad bounds
b = geolib.geohash.bounds(
geolib.geohash.encode(lat=32.8271484375, lon=-96.8115234375, precision=5)
)
print(b)
gdf = gpd.GeoDataFrame(
pd.DataFrame({"id": [0], "b": [b]}).assign(
geometry=lambda d: d["b"].apply(
lambda b: shapely.geometry.box(b.sw.lon, b.sw.lat, b.ne.lon, b.ne.lat)
)
),
crs="epsg:4326",
)
gdf.explore(height=300, width=300)
output
Bounds(sw=SouthWest(lat=32.8271484375, lon=-96.8115234375), ne=NorthEast(lat=32.87109375, lon=-96.767578125))
I'm trying to draw some circles to outline koala sightings around Brisbane Aus. When I try and run it in jupyter, it draws the map and if I replace the coordinate[["decimalLatitude"],coordinate["decimalLongitude"]] with actual values, it displays, but otherwise it doesn't. Here's my code and a sample pic of the data.
import folium
map_of_koala_sightings = folium.Map(
location =[-27.470125,153.021072],
zoom_start=13, tiles='Stamen Terrain'
)
for coordinate in koala_df:
try:
folium.Circle(
radius=300,
location = coordinate[["decimalLatitude"],coordinate["decimalLongitude"]],
color='#3388ff',
fill=True).add_to(map_of_koala_sightings)
except:
pass
map_of_koala_sightings
Sample Data
This works for me (with a subset of coordinates).
import folium
import pandas as pd
koala_df = pd.DataFrame(columns = ['decimalLatitude','decimalLongitude'],
data = [[-26.770484,152.838467],
[-28.103458,153.375882],
[-26.4,146.25]])
print(koala_df.head())
map_of_koala_sightings = folium.Map(
location =[-27.470125,153.021072],
zoom_start=5, tiles='Stamen Terrain'
)
for idx,coordinate in koala_df.iterrows():
folium.Circle(radius=300,
location = [coordinate['decimalLatitude'],coordinate['decimalLongitude']],
color='#3388ff',
fill=True).add_to(map_of_koala_sightings)
#map_of_koala_sightings
#For saving to html file
map_of_koala_sightings.save('koalas.html')
Output:
decimalLatitude decimalLongitude
0 -26.770484 152.838467
1 -28.103458 153.375882
2 -26.400000 146.250000
and 'koalas.html' contains:
I have a DataFrame as below, I want to convert data to a multi polygon DataFrame, because I want to plot each multi polygon on a map.
I know how to convert if I have two data point, but with 6 data point, I don't know how to convert it. can anyone help me please.
geometry = [Point(xy) for xy in zip(neightrip_counts_.lan0, neightrip_counts_.long0)]
geometry
#neightrip_counts_.lan1, neightrip_counts_.long1,neightrip_counts_.lan2, neightrip_counts_.long2
lan0 long0 lan1 long1 lan2 long2
0 59.915667 10.777567 59.916738 10.779916 59.914943 10.773977
1 59.929853 10.711515 59.929435 10.713682 59.927596 10.710033
2 59.939230 10.759170 59.937205 10.760581 59.943750 10.760306
3 59.912520 10.762240 59.911594 10.761774 59.912347 10.763815
4 59.929634 10.732839 59.927140 10.730981 59.931081 10.736003
Let me rename the dataframe neightrip_counts_ as df for brevity. Here is the relevant code that will create a polygon for each row of dataframe.
df['geometry'] = [Polygon([(z[0],z[1]), (z[2],z[3]), (z[4],z[5])]) for z in zip(df.long0, df.lan0, df.long1, df.lan1, df.long2, df.lan2)]
gpdf = df.set_geometry("geometry", drop=True)
gpdf.plot()
By the way, you must be careful about the sequence of (long, lat).
start_coords = [ gdf.centroid[0].x, gdf.centroid[0].y] # is wrong
Use this in stead.
start_coords = [ gdf.centroid[0].y, gdf.centroid[0].x]
Edit
For the benefits of the readers, here is the complete runnable code:
import pandas as pd
import geopandas as gpd
from io import StringIO
from shapely.geometry import Polygon, Point, LineString
import numpy as np
import folium
data1 = """index lan0 long0 lan1 long1 lan2 long2
0 59.915667 10.777567 59.916738 10.779916 59.914943 10.773977
1 59.929853 10.711515 59.929435 10.713682 59.927596 10.710033
2 59.939230 10.759170 59.937205 10.760581 59.943750 10.760306
3 59.912520 10.762240 59.911594 10.761774 59.912347 10.763815
4 59.929634 10.732839 59.927140 10.730981 59.931081 10.736003"""
# read/parse data into dataframe
df0 = pd.read_csv(StringIO(data1), sep='\s+', index_col='index')
# create `geometry` column
df0['geometry'] = [Polygon([(xy[0],xy[1]), (xy[2],xy[3]), (xy[4],xy[5])]) \
for xy in zip(df0.long0, df0.lan0, df0.long1, df0.lan1, df0.long2, df0.lan2)]
# set geometry
gpdf = df0.set_geometry("geometry", drop=True)
# do check plot. (uncomment next line)
#gpdf.plot()
# make geojson
center_pt = gpdf.centroid[0].y, gpdf.centroid[0].x
gdf_json = gpdf.to_json()
# plot the geojson on the folium webmap
webmap = folium.Map(location = center_pt, zoom_start = 13, min_zoom = 3)
folium.GeoJson(gdf_json, name='data_layer_1').add_to(webmap)
# this opens the webmap
webmap
Output screen capture (of interactive webmap):
Try this, assuming the 'lan' is latitude.
import geopandas as gpd
from shapely.geometry import Polygon
import numpy as np
import pandas as pd
import folium
# ....
def addpolygeom(row):
row_array = np.array(row)
# split dataframe row to a list of tuples (lat, lon)
coords = [tuple(i)[::-1] for i in np.split(row_array, range(2, row_array.shape[0], 2))]
polygon = Polygon(coords)
return polygon
# Convert points to shapely geometry
neightrip_counts_['geometry'] = neightrip_counts_.apply(lambda x: addpolygeom(x), axis=1)
# Create a GeoDataFrame
gdf = gpd.GeoDataFrame(neightrip_counts_, geometry='geometry')
start_coords = [ gdf.centroid[0].y, gdf.centroid[0].x]
gdf_json = gdf.to_json()
map = folium.Map(start_coords, zoom_start=4)
folium.GeoJson(gdf_json, name='mypolygons').add_to(map)
This is what I have so far:
import folium
m = folium.Map(
location=[43.761539, -79.411079],
tiles="Stamen Toner",
zoom_start=11
)
m.save("index.html")
folium.GeoJson("file.geojson").add_to(m)
m
Up until the folium.GeoJson... line the map shows up but the overlay makes nothing render
You need to add a LayerControl():
import folium
m = folium.Map(
location=[43.761539, -79.411079],
tiles="Stamen Toner",
zoom_start=11
)
folium.GeoJson("file.geojson", name="geojson").add_to(m)
folium.LayerControl().add_to(m)
m.save("index.html")
m
I've been working for a while with Choropleth and Cluster marker maps in Folium (which are great). My question is whether it is possible to combine them in one map, which is so that I can see how much one variable affects another. I can get both map types to work individually so no problems there. This is my attempted code to combine the two so far:
import pandas as pd
import folium
from folium.plugins import MarkerCluster
input_filename="input_filename.csv"
df = pd.read_csv(input_filename,encoding='utf8')
geo = 'blah.json'
comparison = 'comparison.csv'
comparison_data = pd.read_csv(comparison)
m = folium.Map(location=[Lat,Lon], zoom_start=12)
folium.Choropleth(
geo_data=geo,
name='choropleth',
data=comparison_data,
columns=['col1','col2'],
key_on='feature.properties.ID',
fill_color='OrRd',
fill_opacity=0.5,
line_opacity=0.5,
legend_name='Blah (%)'
).add_to(m)
folium.LayerControl().add_to(m)
marker_cluster = MarkerCluster().add_to(m)
for row in df.itertuples():
folium.Marker(location=[row.Lat,row.Lon],popup=row.Postcode).add_to(marker_cluster)
m
It produces the choropleth but won't layer the cluster markers as well. Worth noting that I've had a problem with cluster markers separately where they wouldn't display in Jupyter notebook, but I got around it by saving the file as an html, which was then viewable.
Ok so I've solved it, really pleased!! The solution was to do the marker cluster first, and then follow-up with the Choropleth:
import pandas as pd
import folium
from folium.plugins import MarkerCluster
m = folium.Map(location=[Lat,Lon], zoom_start=12)
input_filename="input_filename.csv"
df = pd.read_csv(input_filename,encoding='utf8')
geo = 'blah.json'
comparison = 'comparison.csv'
comparison_data = pd.read_csv(comparison)
folium.LayerControl().add_to(m)
marker_cluster = MarkerCluster().add_to(m)
for row in df.itertuples():
folium.Marker(location=[row.Lat,row.Lon],popup=row.Postcode).add_to(marker_cluster)
folium.Choropleth(
geo_data=geo,
name='choropleth',
data=comparison_data,
columns=['col1','col2'],
key_on='feature.properties.ID',
fill_color='OrRd',
fill_opacity=0.5,
line_opacity=0.5,
legend_name='Blah (%)'
).add_to(m)
m
from random import randint
import folium
def rgb_to_hex(rgb):
return '#%02x%02x%02x' % rgb
mp = folium.Map(location=[40.6, -73.7], scale = 10)
colors = []
while len(colors) != 50:
r = randint(0, 255)
g = randint(0, 255)
b = randint(0, 255)
if rgb_to_hex((r, g, b)) not in colors:
colors.append(rgb_to_hex((r, g, b)))
for j in range(df.shape[0]):
lat = df.iloc[j]['latitude']
lon = df.iloc[j]['longitude']
color = colors[int(df.iloc[j]['clust'])]
folium.Circle(location=[lat, lon], radius=8, color = color).add_to(mp)