'How can I make a list in a popup in a map with folium?
I am using pandas and folium to display different companies for each unique city in a Dataframe.
The first dataframe is something like this:
| city | count | id | company_name | geo_loc | lat | lon | |
|---|---|---|---|---|---|---|---|
| 0 | USA | 2 | 7254 | Advanced Heat Treat Corp. | (42.7756032, -94.1956133) | 39.783730 | -94.1956133 |
| 1 | Cedar Rapids, Iowa, United States | 4 | 7254 | Advanced Heat Treat Corp. | (39.7837304, -100.445882) | 39.7837304 | -100.445882 |
| 2 | Humboldt, Iowa, United States | 2 | 7254 | Corn Belt Power Cooperative | (39.7837304, -100.445882) | 39.7837304 | -100.445882 |
| 3 | Humboldt, Iowa, United States | 4 | 7258 | Corridor Careers | (42.5361805, -92.447758) | 42.5361805 | -92.447758 |
The second one is something like this. With just the necessary information:
| city | company_name | |
|---|---|---|
| 0 | Cedar Falls, Iowa, United States | Far Reach , Martin Bros |
| 1 | Cedar Rapids, Iowa, United States | Collabrance , Corridor Careers |
| 2 | Davenport, Iowa, United States | McCarthy Improvement |
| 3 | Des Moines, Iowa, United States | Flynn Wright , Iowa Public Radio , Medico ... |
| 4 | Humboldt, Iowa, United States | Corn Belt Power Cooperative |
#Necessary libraries
import folium
import pandas as pd
import numpy as np
from geopy.geocoders import Nominatim
import folium
#Reading csv and obtaining locations
data = pd.read_csv('test.csv',error_bad_lines = False)
geolocator = Nominatim(user_agent= 'app')
locations = pd.DataFrame({'Name': data['city'].unique()})
lat_lon = []
for location in data['city']:
location = geolocator.geocode(location,timeout=100)
if location is None:
lat_lon.append(np.nan)
else:
geo = (location.latitude, location.longitude)
lat_lon.append(geo)
data['geo_loc'] = lat_lon
#Unique values
Comp_locations = pd.DataFrame(data['city'].value_counts().reset_index())
#Grouping to obtain just city and the companies
Companies = data.groupby('city')['company_name'].unique()
Companies_2 = Companies.to_frame().reset_index()
Companies_2 = Companies_2.rename(columns= {0: 'city',1: 'companies'})
Comp_locations.columns = ['city', 'count']
Companies_locations = Comp_locations.merge(data, on='city', how='right').dropna()
lat,lon = zip(*np.array(Companies_locations['geo_loc']))
Companies_locations['lat'] = lat
Companies_locations['lon'] = lon
#Bluemarkers to indicate each city
m = folium.Map(tiles="OpenStreetMap", zoom_start=2)
Companies_locations["count"] = Companies_locations["count"].astype(str)
for i in range(0,len(Companies_locations)):
folium.Marker(
location=[Companies_locations.iloc[i]['lat'], Companies_locations.iloc[i]['lon']],
popup=Companies_locations.iloc[i]['city'],
).add_to(m)
m
This is what I have with bluemarkers City marks
Add marker one by one on the map. This is to show the companies names
for i in range(0,len(Companies_locations)):
html=f"""
<h1> {Companies_locations.iloc[i]['count']}</h1>
<p>Companies:</p>
<ul>
<li>{Companies_2.iloc[i]['company_name']}<li>
</ul>
</p>
<p>And here the company <a href="{Companies_locations.iloc[i]['url']}" target = "_blank">link </a></p>
"""
iframe = folium.IFrame(html=html, width=200, height=200)
popup = folium.Popup(iframe, max_width=2650)
folium.Marker(
location=[Companies_locations.iloc[i]['lat'], Companies_locations.iloc[i]['lon']],
popup=popup,
icon=folium.DivIcon(html=f"""
<div><svg>
<circle cx="5" cy="5" r="4" fill="#69b3a2" opacity="0.4"/>
<rect x="3", y="3" width="3" height="3", fill="red", opacity=".3"
</svg></div>""")
).add_to(m)
m
This is what I have with the popups. For each bullet-mark I desire to display the companies names (the number above is the quatinty of companies in this city).

But I have the following error:
"IndexError: single positional indexer is out-of-bounds"
How can I manage my previous Dataframe to iterate over it and print each company with a bullet mark?
Solution 1:[1]
I have never used geopy, so I looked for sample data to show your assignment in code without it. I got the sample data from here and created the code. I have company information in the columns of the data frame I used, so I added a new loop process and concatenated the html strings to create the bullet points.
import folium
import pandas as pd
import numpy as np
import folium
# sample data from https://uscompanydata.com/california-business-list/
data = pd.read_csv('./data/Company-Database-Sample.csv', sep=',')
data = data[['Company Name', 'Job Title', 'City','State', 'Zip', 'County Code', 'Area Code', 'Founded', 'Website Address', 'Employee ', 'Latitude', 'Longitude']]
data.dropna(subset=['Latitude', 'Longitude'], inplace=True)
data.reset_index(drop=True, inplace=True)
data.head()
Company Name Job Title City State Zip County Code Area Code Founded Website Address Employee Latitude Longitude
0 Phillips Chrysler Jeep Dodge General Manager Ocala FL 34471 12083.0 352 1997.0 www.phillipschrysler.com 37 29.153831 -82.125527
1 Industrial Conveyor Systems Chief Executive Officer Cutler Bay FL 33157 12086.0 305 1979.0 www.icsequipment.com 10 25.593898 -80.359226
2 Prism Optical Inc Owner Miami FL 33168 12086.0 305 1959.0 www.prismoptical.com 9 25.875858 -80.210274
3 Piaggio America Inc. President West Palm Bch FL 33406 12099.0 561 2004.0 www.piaggioaero.com 5 26.678277 -80.079994
4 A Busy Traveler Transportation Owner Merritt Island FL 32954 12009.0 321 1994.0 www.abusytraveler.com 8 28.357230 -80.694249
m = folium.Map(tiles="OpenStreetMap", location=[data['Latitude'].mean(), data['Longitude'].mean()], zoom_start=7)
for i in range(len(data)):
profiles = ''
for info in data.loc[i,['Company Name','Job Title','Employee ','Founded']]:
item = '<{0}>{1}</{0}>'.format('li',info)
profiles += item
#print(profiles)
html=f"""
<h1>{data.iloc[i]['Zip']}</h1>
<p>Companies:</p>
<ul>
{profiles}
</ul>
</p>
<p>And here the company <a href="{data.iloc[i]['Website Address']}" target = "_blank">link </a></p>
"""
iframe = folium.IFrame(html=html, width=300, height=250)
popup = folium.Popup(iframe, max_width=2650)
folium.Marker(
location=[data.iloc[i]['Latitude'], data.iloc[i]['Longitude']],
popup=popup,
icon=folium.DivIcon(html=f"""
<div><svg>
<circle cx="5" cy="5" r="4" fill="#69b3a2" opacity="0.7"/>
<rect x="3", y="3" width="3" height="3", fill="red", opacity=".7"
</svg></div>""")
).add_to(m)
m
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 | r-beginners |

