Create a bubble map from excel data using python folium and pandas

folium_bubble_map

Challenge - Create a bubble map from excel data using python folium and pandas

Table of Contents

Skills Required

Please make sure to have all the skills mentioned above to understand and execute the code mentioned below. Go through the above skills if necessary for reference or revision


In this post we will learn how to draw a bubble map from excel data using pandas and folium python libraries

Challenge

  • Plot the capacities of power plants provided in an excel file on a geographical bubble map
  • The bubbles of wind plants will be blue and bubbles of solar plants will be red
  • When user clicks on a bubble, it’s information should be shown on a popup
  • There should be legend at the bottom left of the map for explaining the bubble colors
    bubble_map_demo_data

Files

  • Power plants excel file can be found here
  • Country borders GeoJson file can be found here

Solution

The whole program can be broken down into the following tasks

  • Read all the power plants information from excel file using pandas
  • Create a simple map with a desired map center and map zoom
  • Draw country borders using folium.GeoJson layer
  • Using folium FeatureGroup, create a map layer on which circles will be drawn
  • Iterate through each power plant and draw a circle on the map. The color of the circle will be based on the fuel type of the power plant (Solar-red, Wind-blue)
  • Inject HTML into the map to create a legend at the bottom left
  • Create a layer switcher control for switching ON and OFF the layers

Code

import pandas as pd
import folium

# read excel data as dataframe
dataDf = pd.read_excel('power_plants.xlsx')

# initialize a map with center and zoom
mapObj = folium.Map(location=[21.437730075416685, 77.255859375],
                     zoom_start=7, tiles='openstreetmap')
# folium.TileLayer('stamenterrain', attr="stamenterrain").add_to(mapObj)

# create GeoJson layer to draw country borders
# style options - https://leafletjs.com/reference-1.7.1.html#path
bordersStyle = {"color": 'green', 'weight': 2, 'fillOpacity': 0}
bordersLayer = folium.GeoJson(
    data="states_india.geojson",
    name="Borders",
    style_function=lambda x: bordersStyle)
bordersLayer.add_to(mapObj)

# create a layer for bubble map using FeatureGroup
powerPlantsLayer = folium.FeatureGroup("Power Plants")
# add the created layer to the map
powerPlantsLayer.add_to(mapObj)

# iterate through each dataframe row
for i in range(len(dataDf)):
    areaStr = dataDf.iloc[i]['area']
    fuelStr = dataDf.iloc[i]['fuel']
    capVal = dataDf.iloc[i]['capacity']
    # derive the circle color
    clr = "blue" if fuelStr.lower() == 'wind' else "red"
    # derive the circle radius
    radius = capVal*100
    # derive the circle pop up html content 
    popUpStr = 'Area - {0}<br>Fuel - {1}<br>Capacity - {2} MW'.format(
        areaStr, fuelStr, capVal)
    # draw a circle for the power plant on the layer
    folium.Circle(
        location=[dataDf.iloc[i]['lat'], dataDf.iloc[i]['lng']],
        popup=folium.Popup(popUpStr, min_width=100, max_width=700),
        radius=radius,
        color=clr,
        weight=2,
        fill=True,
        fill_color=clr,
        fill_opacity=0.1
    ).add_to(powerPlantsLayer)


# add layer control over the map
folium.LayerControl().add_to(mapObj)

# html to be injected for displaying legend
legendHtml = '''
     <div style="position: fixed; 
     bottom: 50px; left: 50px; width: 150px; height: 70px; 
     border:2px solid grey; z-index:9999; font-size:14px;
     ">&nbsp; Fuel Types <br>
     &nbsp; <i class="fa fa-circle"
                  style="color:blue"></i> &nbsp; Wind<br>
     &nbsp; <i class="fa fa-circle"
                  style="color:red"></i> &nbsp; Solar<br>
      </div>
     '''

# inject html corresponding to the legend into the map
mapObj.get_root().html.add_child(folium.Element(legendHtml))

# save the map as html file
mapObj.save('output.html')

bubble_map_demo

Video

The video for this post can be seen here


References


Table of Contents

Comments