DocZerø
DocZerø

Reputation: 8557

Unable to use scatter plot in Basemap

I'm following the tutorial Visualization: Mapping Global Earthquake Activity to get more familiar with Basemap.

What I'm trying to do is scatter plot the data in a Pandas DataFrame on the the map.

Initialization code for my map:

my_map = Basemap(projection='merc', 
                 lat_0=50.93, lon_0=4.13,
                 llcrnrlat=49.339950, llcrnrlon=1.777668,
                 urcrnrlat=51.601360, urcrnrlon=6.925303,
                 resolution='h', area_thresh=1.0)

my_map.drawcoastlines()
my_map.drawcountries()
my_map.fillcontinents(color='coral')
my_map.drawmapboundary()

So far so good. Now for the actual data. The structure of my df looks like this:

lat    float64
lon    float64
id       int64
dtype: object

Sample:

|      |     lat |     lon |   id |
|-----:|--------:|--------:|-----:|
| 1083 | 51.8205 | 4.62573 |    7 |
|  211 | 50.5155 | 3.89612 |    1 |
|   89 | 50.3397 | 4.61034 |    1 |

The id columns is actually a count (the df is an aggregation of a more detailed df). The value in the id column should be used to define the marker size.

I started with this simple plot (not yet a scatter plot), which works.

x,y = my_map(df_loc.lon.tolist(), df_loc.lat.tolist())
my_map.plot(x, y, 'bo', markersize=10)
plt.show()

Plot

Because I want the marker size to be dependant of the count (i.e. the id column), I need to switch from plot to scatter.

If I try: my_map.scatter(x, y, s=10) (i.e. with a fixed size), the result will be an empty map (no points are drawn).

I would appreciate if you could tell me what I'm doing wrong. The strange thing is, a regular scatter plot works just fine (maybe a bad comparison, but still):

plt.scatter(df_loc.lon, df_loc.lat, s=df_loc.id, alpha=.3)
plt.ylim(49.339950, 51.601360)
plt.xlim(1.777668, 6.925303)

scatter

Extra credit:

From what I've read in the documentation, the additional step of converting lat/lon to map projection should be unnecessary if the latlon=True parameter is specified.

If latlon keyword is set to True, x,y are intrepreted as longitude and latitude in degrees. Data and longitudes are automatically shifted to match map projection region for cylindrical and pseudocylindrical projections, and x,y are transformed to map projection coordinates.

However, if I change this:

x,y = my_map(df_loc.lon.tolist(), df_loc.lat.tolist())
my_map.plot(x, y, 'bo', markersize=10)

to this:

my_map.plot(df_loc.lon, df_loc.lat, 'bo', latlon=True)

I end up with the error:

SystemError: <class 'RuntimeError'> returned a result with an error set

Is this not what the latlon parameter is supposed to be used for?

Update:

It seems that the plot function doesn't like to have Pandas Series objects passed into it as x and y arguments. This code does work however (difference is the additional tolist() call):

my_map.plot(df_loc.lon.tolist(), 
            df_loc.lat.tolist(), 
            'bo', 
            latlon=True)

Upvotes: 0

Views: 1793

Answers (1)

tmdavison
tmdavison

Reputation: 69116

This is an issue with the zorder. Specifically, that the fillcontinents zorder is greater than that of the scatter points, so the scatter points are ending up beneath the fill for the continents (and thus are not visible).

Two ways to fix this:

  1. Reduce the fillcontinents zorder:

    my_map.fillcontinents(color='coral', zorder=0)
    
  2. Increase the scatter zorder:

    my_map.scatter(x, y, s=10, zorder=10)
    

Upvotes: 3

Related Questions