Question

Sorry if this question is simple I'm a newb to using Python and Basemap. Anyway I'm trying to plot the path of 20 hurricanes on a map (graph). The map itself and the legend show up perfectly but the paths of the hurricanes do not. Also I'm not getting any traceback messages but I think I have an idea of where my problem may be. Could someone please tell me where I went wrong.

Here's a sample of the csv file:

Year, Name, Type, Latitude, Longitude
1957,AUDREY,HU, 21.6, 93.3
1957,AUDREY,HU,22.0,  93.4
1957,AUDREY,HU,22.6,  93.5
1969,AUDREY,HU,28.2,99.6
1957,AUDREY,HU,26.5,93.8
1957,AUDREY,HU,27.9,93.8
1957,AUDREY,HU,29.3,95
1957,AUDREY,HU,27.9,93.8
1957,AUDREY,HU,29.3,93.8
1957,AUDREY,HU,30.7,93.5
1969,CAMILLE,HU, 21.6,99.3
1969,CAMILLE,HU,22.0,98.4
1969,CAMILLE,HU,22.6,90.5
1969,CAMILLE,HU,23.2,93.6

Here's the code I have so far:

import numpy as np
from mpl_toolkits.basemap import Basemap
import matplotlib.pyplot as plt
import csv, os, scipy
import pandas
from PIL import *


data = np.loadtxt('louisianastormb.csv',dtype=np.str,delimiter=',',skiprows=1)
'''print data'''
fig = plt.figure(figsize=(12,12))

ax = fig.add_axes([0.1,0.1,0.8,0.8])

m = Basemap(llcrnrlon=-100.,llcrnrlat=0.,urcrnrlon=-20.,urcrnrlat=57.,
            projection='lcc',lat_1=20.,lat_2=40.,lon_0=-60.,
            resolution ='l',area_thresh=1000.)

m.bluemarble()
m.drawcoastlines(linewidth=0.5)
m.drawcountries(linewidth=0.5)
m.drawstates(linewidth=0.5)

# Creates parallels and meridians
m.drawparallels(np.arange(10.,35.,5.),labels=[1,0,0,1])
m.drawmeridians(np.arange(-120.,-80.,5.),labels=[1,0,0,1])
m.drawmapboundary(fill_color='aqua')
color_dict = {'AUDREY': 'red', 'ETHEL': 'white', 'BETSY': 'yellow','CAMILLE': 'blue', 'CARMEN': 'green','BABE': 'purple', }


colnames = ['Year','Name','Type','Latitude','Longitude']
data = pandas.read_csv('louisianastormb.csv', names=colnames)
names = list(data.Name)
lat = list(data.Latitude)
long = list(data.Longitude)
colorName = list(data.Name)
#print lat
#print long
lat.pop(0)
long.pop(0)
colorName.pop(0)
latitude= map(float, lat)
longitude = map(float, long)
x, y = m(latitude,longitude)
#Plots points on map
for colorName in color_dict.keys():
    plt.plot(x,y,linestyle ='-',label=colorName,color=color_dict[colorName], linewidth=5 )
    lg = plt.legend()
    lg.get_frame().set_facecolor('grey')
plt.show()
Was it helpful?

Solution

two (okay I lied, should be there) problems with your code

i, your input longitude should be negative to be within the boundary you defined for your basemap, so add this after before converting to x and y

longitude = [-i for i in longitude]

ii, your coordinate conversion line is wrong, you should swap lon and lat in the argument list

x, y = m(longitude, latitude)

instead of

x, y = m(latitude,longitude)

EDIT:

okay, the second question that OP posted in the comments, please check the complete code below and please pay attention to the changes I've made compared to yours

# Last-modified: 21 Oct 2013 05:35:16 PM

import numpy as np
from mpl_toolkits.basemap import Basemap
import matplotlib.pyplot as plt
import csv, os, scipy
import pandas
from PIL import *


data = np.loadtxt('louisianastormb.csv',dtype=np.str,delimiter=',',skiprows=1)
'''print data'''
fig = plt.figure(figsize=(12,12))

ax = fig.add_axes([0.1,0.1,0.8,0.8])

m = Basemap(llcrnrlon=-100.,llcrnrlat=0.,urcrnrlon=-20.,urcrnrlat=57.,
            projection='lcc',lat_1=20.,lat_2=40.,lon_0=-60.,
            resolution ='l',area_thresh=1000.)

m.drawcoastlines(linewidth=0.5)
m.drawcountries(linewidth=0.5)
m.drawstates(linewidth=0.5)
# m.bluemarble(ax=ax)

# Creates parallels and meridians
m.drawparallels(np.arange(10.,35.,5.),labels=[1,0,0,1])
m.drawmeridians(np.arange(-120.,-80.,5.),labels=[1,0,0,1])
m.drawmapboundary(fill_color='aqua')
color_dict = {'AUDREY': 'red', 'ETHEL': 'white', 'BETSY': 'yellow','CAMILLE': 'blue', 'CARMEN': 'green','BABE': 'purple', }

colnames = ['Year','Name','Type','Latitude','Longitude']
data = pandas.read_csv('louisianastormb.csv', names=colnames)
names = list(data.Name)
lat = list(data.Latitude)
long = list(data.Longitude)
colorNames = list(data.Name)
#print lat
#print long
lat.pop(0)
long.pop(0)
colorNames.pop(0)
latitude= map(float, lat)
longitude = map(float, long)
# added by nye17
longitude = [-i for i in longitude]
# x, y = m(latitude,longitude)
x, y = m(longitude,latitude)
# convert to numpy arrays
x = np.atleast_1d(x)
y = np.atleast_1d(y)
colorNames = np.atleast_1d(colorNames)
#Plots points on map
for colorName in color_dict.keys():
    plt.plot(x[colorName == colorNames],y[colorName == colorNames],linestyle ='-',label=colorName,color=color_dict[colorName], linewidth=5 )
    lg = plt.legend()
    lg.get_frame().set_facecolor('grey')
plt.show()

enter image description here

OTHER TIPS

I think your difficulty is not so much in Basemap as in the plotting. Instead of plotting the entire x/y data set you need to find the x/y points corresponding on hurricane Z. Then plot only those points in a certain color c. Then find the points corresponding to the next hurricane etc...

The below, while not using the Basemap data structure should provide a starting point for plotting subsets of points based on some selector vector.

#given a list of x,y coordinates with a  label we'll plot each line individually

#first construct some points to plot
x1 = [1,1.1,1.2,1.3, 2.0,2.2,2.3, 4,3.9,3.8,3.7]
y1 = [5,5.1,5.2,5.3, 6.0,6.2,6.3, 2,2.1,2.2,2.3]
pointNames = []
#generate some labels
pointNames.extend(['a']*4)
pointNames.extend(['b']*3)
pointNames.extend(['c']*4)

#make things easy by casting to numpy arrays to allow for easier indexing
x1 = numpy.array(x1)
y1 = numpy.array(y1)
pointNames = numpy.array(pointNames)

for elem in ['a','b','c']:
  selector = pointNames==elem
  subsetX = x1[selector]
  subsetY = y1[selector]
  #now plot subsetX vs subsetY in color Z
  plot(subsetX,subsetY,'*-')

show()
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top