Update:
This tutorial has been updated and moved to http://introtopython.org/visualization_earthquakes.html.
In this part of the tutorial, we will see how to plot points on a map. We will start out by plotting some communities on Baranof Island in southeast Alaska. Here is our code so far, which creates a map of Baranof Island:
from mpl_toolkits.basemap import Basemap import matplotlib.pyplot as plt import numpy as np map = Basemap(projection='merc', lat_0 = 57, lon_0 = -135, resolut ion = 'h', area_thresh = 0.1, llcrnrlon=-136.25, llcrnrlat=56.0, urcrnrlon=-134.25, urcrnrlat=57.75) map.drawcoastlines() map.drawcountries() map.fillcontinents(color = 'coral') map.drawmapboundary() plt.show()
and here is the map we have:
It is a testament to the hard work of many other people that we can create a map like this in less than 15 lines of code! Now let’s add some points to this map. I live in Sitka, the largest community on Baranof Island, so let’s add a point showing Sitka’s location. Add the following lines just before plt.show():
from mpl_toolkits.basemap import Basemap import matplotlib.pyplot as plt import numpy as np map = Basemap(projection='merc', lat_0 = 57, lon_0 = -135, resolut ion = 'h', area_thresh = 0.1, llcrnrlon=-136.25, llcrnrlat=56.0, urcrnrlon=-134.25, urcrnrlat=57.75) map.drawcoastlines() map.drawcountries() map.fillcontinents(color = 'coral') map.drawmapboundary() lon = -135.3318 lat = 57.0799 x,y = map(lon, lat) map.plot(x, y, 'bo', markersize=24) plt.show()
The only non-obvious line here is the ‘bo’ argument, which tells basemap to use a blue circle for the point. There are quite a number of colors and symbols you can use. For more choices, see the documentation for the matplotlib.pyplot.plot function. The default marker size is 6, but that was too small on this particular map. A markersize of 24 shows up nicely on this map:
Plotting a single point is nice, but we often want to plot a large set of points on a map. There are two other communities on Baranof Island, so let’s show where those two communities are on this map. We store the latitudes and longitudes of our points in two separate lists, map those to x and y coordinates, and plot those points on the map. With more dots on the map, we also want to reduce the marker size a little:
from mpl_toolkits.basemap import Basemap import matplotlib.pyplot as plt import numpy as np map = Basemap(projection='merc', lat_0 = 57, lon_0 = -135, resolut ion = 'h', area_thresh = 0.1, llcrnrlon=-136.25, llcrnrlat=56.0, urcrnrlon=-134.25, urcrnrlat=57.75) map.drawcoastlines() map.drawcountries() map.fillcontinents(color = 'coral') map.drawmapboundary() lons = [-135.3318, -134.8331, -134.6572] lats = [57.0799, 57.0894, 56.2399] x,y = map(lons, lats) map.plot(x, y, 'bo', markersize=18) plt.show()
Now let’s label these three points. We make a list of our labels, and loop through that list. We need to include the x and y values for each point in this loop, so Basemap can figure out where to place each label.
from mpl_toolkits.basemap import Basemap import matplotlib.pyplot as plt import numpy as np map = Basemap(projection='merc', lat_0 = 57, lon_0 = -135, resolut ion = 'h', area_thresh = 0.1, llcrnrlon=-136.25, llcrnrlat=56.0, urcrnrlon=-134.25, urcrnrlat=57.75) map.drawcoastlines() map.drawcountries() map.fillcontinents(color = 'coral') map.drawmapboundary() lons = [-135.3318, -134.8331, -134.6572] lats = [57.0799, 57.0894, 56.2399] x,y = map(lons, lats) map.plot(x, y, 'bo', markersize=18) labels = ['Sitka', 'Baranof Warm Springs', 'Port Alexander'] for label, xpt, ypt in zip(labels, x, y): plt.text(xpt, ypt, label) plt.show()
Our towns are now labeled, but the labels start right on top of our points:
We can add offsets to these points, so they are not right on top of the points. Let’s move all of the labels a little up and to the right. (If you are curious, these offsets are in “map projection coordinates“, which are measured in meters. This means our code actually places the labels 10 km to the east and 5 km to the north of the actual townsites.)
from mpl_toolkits.basemap import Basemap import matplotlib.pyplot as plt import numpy as np map = Basemap(projection='merc', lat_0 = 57, lon_0 = -135, resolut ion = 'h', area_thresh = 0.1, llcrnrlon=-136.25, llcrnrlat=56.0, urcrnrlon=-134.25, urcrnrlat=57.75) map.drawcoastlines() map.drawcountries() map.fillcontinents(color = 'coral') map.drawmapboundary() lons = [-135.3318, -134.8331, -134.6572] lats = [57.0799, 57.0894, 56.2399] x,y = map(lons, lats) map.plot(x, y, 'bo', markersize=18) labels = ['Sitka', 'Baranof Warm Springs', 'Port Alexander'] for label, xpt, ypt in zip(labels, x, y): plt.text(xpt+10000, ypt+5000, label) plt.show()
This is better, but on a map of this scale the same offset does not work well for all points. We could plot each label individually, but it is easier to make two lists to store our offsets:
from mpl_toolkits.basemap import Basemap import matplotlib.pyplot as plt import numpy as np map = Basemap(projection='merc', lat_0 = 57, lon_0 = -135, resolut ion = 'h', area_thresh = 0.1, llcrnrlon=-136.25, llcrnrlat=56.0, urcrnrlon=-134.25, urcrnrlat=57.75) map.drawcoastlines() map.drawcountries() map.fillcontinents(color = 'coral') map.drawmapboundary() lons = [-135.3318, -134.8331, -134.6572] lats = [57.0799, 57.0894, 56.2399] x,y = map(lons, lats) map.plot(x, y, 'bo', markersize=18) labels = ['Sitka', 'Baranof\n Warm Springs', 'Port Alexander'] x_offsets = [10000, -30000, -25000] y_offsets = [5000, -25000, -25000] for label, xpt, ypt, x_offset, y_offset in zip(labels, x, y, x_offsets, y_offsets): plt.text(xpt+x_offset, ypt+y_offset, label) plt.show()
There is no easy way to keep “Baranof Warm Springs” from crossing a border, but the use of newlines within a label makes it reasonably legible. Now that we know how to add points to a map, we will move on to larger data sets.
Next: Plotting global earthquake activity
Back to Tutorial contents
Thanks for the tutorial, it was very helpful in building my map today!
Thank You, your tutorial very helpul.
Great tutorial. Thank you so much.
You can improve your source code by not overriding builtins. In this case map keyword was overriden and this fragment become weird for me:
lon = -135.3318
lat = 57.0799
x,y = map(lon, lat)
Because I assumed traditional meaning of map.
Thanks, that’s a great point. I’ll be updating the project shortly, and I’ll find another name for the map variable.