Wednesday, October 2, 2019

Building a Simple World Map

Using the data from the previous post we'll build a simple world map as shown in the following program:

import json
from plotly.graph_objs import Scattergeo, Layout
from plotly import offline

# Explore the structure of the data.
filename = 'data/eq_data_1_day_m1.json'
with open(filename) as f:
    all_eq_data = json.load(f)

all_eq_dicts = all_eq_data['features']

mags, lons, lats = [], [], []
for eq_dict in all_eq_dicts:
    mag = eq_dict['properties']['mag']
    lon = eq_dict['geometry']['coordinates'][0]
    lat = eq_dict['geometry']['coordinates'][1]
    mags.append(mag)
    lons.append(lon)
    lats.append(lat)

# Map the earthquakes.
data = [Scattergeo(lon=lons, lat=lats)]
my_layout = Layout(title='Global Earthquakes')
fig = {'data': data, 'layout': my_layout}
offline.plot(fig, filename='global_earthquakes.html')


In our program we import the Scattergeo chart type and the Layout class, and then import the offline module to render the map. Next we define a list called data. We create the Scattergeo object inside
this list because we can plot more than one data set on any visualization we make.

A Scattergeo chart type allows us to overlay a scatter plot of geographic data on a map. In the simplest use of this chart type, we only need to provide a list of longitudes and a list of latitudes.

Next we give the chart an appropriate title w and create a dictionary called fig that contains the data and the layout Finally, we pass fig to the plot() function along with a descriptive filename for the output.

When you run this file, you should see a map that looks like the one in Figure shown below:



There is s slightly different way to specify the data for a Plotly chart. In the current chart, the data list is defined in one line:

data = [Scattergeo(lon=lons, lat=lats)]

This is one of the simplest ways to define the data for a chart in Plotly. But it’s not the best way when you want to customize the presentation. Here’s an equivalent way to define the data for the current chart:

data = [{
'type': 'scattergeo',
'lon': lons,
'lat': lats,
}]

In this approach, all the information about the data is structured as key-value pairs in a dictionary, however the chart generated will be the same. This format allows us to specify customizations more easily than the previous format.

Let's improve the map’s styling by focusing on aspects of the data that we want to communicate more clearly. The current map shows the location of each earthquake, but it doesn’t communicate the severity of any earthquake. We want viewers to immediately see where the most significant earthquakes occur in the world.

To do this, we’ll change the size of markers depending on the magnitude of each earthquake:

data = [{
    'type': 'scattergeo',
    'lon': lons,
    'lat': lats,
    'text': hover_texts,
    'marker': {
        'size': [5*mag for mag in mags],
        'color': mags,
        'colorscale': 'Viridis',
        'reversescale': True,
        'colorbar': {'title': 'Magnitude'},
    },
}]

Plotly offers a huge variety of customizations you can make to a data series, each of which can be expressed as a key-value pair. Here we’re using the key 'marker' to specify how big each marker on the map should be.

We use a nested dictionary as the value associated with 'marker', because we can specify a number of settings for all the markers in a series. We want the size to correspond to the magnitude of each earthquake. But if we just pass in the mags list, the markers would be too small to easily see the size
differences. We need to multiply the magnitude by a scale factor to get an appropriate marker size. On my screen, a value of 5 works well; a slightly smaller or larger value might work better for your map. We use a list comprehension, which generates an appropriate marker size for each value in the mags list.

When we run this code, we see a map that looks like the one in Figure shown below:


This map is better than the previous one but still a lot can be done to make it much better. For example We can also customize each marker’s color to provide some classification to the severity of each earthquake. We’ll use Plotly’s colorscales to do this. Now I am using another data source, the file eq_data_30_day_m1.json, that includes earthquake data for a 30-day period, and the map will be much more interesting to look at using this larger data set.

The following in previous program shows how to use a colorscale to represent the magnitude of each earthquake:

# Map the earthquakes.
data = [{
    'type': 'scattergeo',
    'lon': lons,
    'lat': lats,
 
    'marker': {
        'size': [5*mag for mag in mags],
        'color': mags,
        'colorscale': 'Viridis',
        'reversescale': True,
        'colorbar': {'title': 'Magnitude'},
         },

         }]

All the significant changes here occur in the 'marker' dictionary, because we’re only modifying the markers’ appearance. The 'color' setting tells Plotly what values it should use to determine where each marker falls on the colorscale. We use the mags list to determine the color that’s used.
The 'colorscale' setting tells Plotly which range of colors to use: 'Viridis' is a colorscale that ranges from dark blue to bright yellow and works well for this data set. We set 'reversescale' to True, because we want to use bright yellow for the lowest values and dark blue for the most severe earthquakes. The 'colorbar' setting allows us to control the appearance of the colorscale shown on the side of the map. Here we title the colorscale 'Magnitude' to make it clear what the colors represent.

When we run the program now, we’ll see a much nicer-looking map as shown in the figure below:


The colorscale shows the severity of individual earthquakes. Plotting this many earthquakes really makes it clear where the tectonic plate boundaries are!

We can also choose from a number of other colorscales. To see the available colorscales, see the following short program:

from plotly import colors
for key in colors.PLOTLY_SCALES.keys():
    print(key)

Plotly stores the colorscales in the colors module. The colorscales are defined in the dictionary PLOTLY_SCALES, and the names of the colorscales serve as the keys in the dictionary. Here’s the output showing all the available colorscales:

Greys
YlGnBu
Greens
YlOrRd
Bluered
RdBu
Reds
Blues
Picnic
Rainbow
Portland
Jet
Hot
Blackbody
Earth
Electric
Viridis
Cividis
------------------
(program exited with code: 0)

Press any key to continue . . .


Now we’ll add some informative text that appears when we hover over the marker representing an earthquake. In addition to showing the longitude and latitude, which appear by default, we’ll show the magnitude and provide a description of the approximate location as well. To make this change, we need to pull a little more data from the file and add it to the dictionary in data as well as shown in the following code:

mags, lons, lats, hover_texts = [], [], [], []
for eq_dict in all_eq_dicts:
    mag = eq_dict['properties']['mag']
    lon = eq_dict['geometry']['coordinates'][0]
    lat = eq_dict['geometry']['coordinates'][1]
    title = eq_dict['properties']['title']
    mags.append(mag)
    lons.append(lon)
    lats.append(lat)
    hover_texts.append(title)

# Map the earthquakes.
data = [{
    'type': 'scattergeo',
    'lon': lons,
    'lat': lats,
    'text': hover_texts,
    'marker': {
        'size': [5*mag for mag in mags],
        'color': mags,
        'colorscale': 'Viridis',
        'reversescale': True,
        'colorbar': {'title': 'Magnitude'},
    },
}]

We first make a list called hover_texts to store the label we’ll use for each marker. The “title” section of the earthquake data contains a descriptive name of the magnitude and location of each earthquake in addition to its longitude and latitude. We pull this information and assign it to the variable title, and then append it to the list hover_texts. When we include the key 'text' in the data object, Plotly uses this value as a label for each marker when the viewer hovers over the marker. When we pass a list that matches the number of markers, Plotly pulls an individual label for each marker it generates.

When we run the program, we should be able to hover over any marker, see a description of where that earthquake took place, and read its exact magnitude. See the output below:



Plotly offers a wide range of ways you can customize the appearance and behavior of your  visualizations. Using Plotly’s many options, you can make charts and maps that show exactly what you want them to.

Here I am ending this post. In the next post we'll discuss about APIs which are used to automatically request specific information from a website—rather than entire pages—and then use that information to generate a visualization.
Share:

0 comments:

Post a Comment