2016-09-28 106 views
4

我知道,强大的包Basemap可以用来绘制美国地图与国家边界。我已经适应了从底图GitHub库这个例子绘制48个州通过各自的人口密度有色: enter image description here如何使用底图(Python)绘制50个州的美国?

现在我的问题是:有没有一个简单的方法来阿拉斯加和夏威夷添加到该地图,并把那些自定义位置,例如左下角?事情是这样的:

enter image description here

import numpy as np 
import matplotlib.pyplot as plt 
from mpl_toolkits.basemap import Basemap as Basemap 
from matplotlib.colors import rgb2hex 
from matplotlib.patches import Polygon 
# Lambert Conformal map of lower 48 states. 
m = Basemap(llcrnrlon=-119,llcrnrlat=22,urcrnrlon=-64,urcrnrlat=49, 
     projection='lcc',lat_1=33,lat_2=45,lon_0=-95) 
# draw state boundaries. 
# data from U.S Census Bureau 
# http://www.census.gov/geo/www/cob/st2000.html 
shp_info = m.readshapefile('st99_d00','states',drawbounds=True) 
# population density by state from 
# http://en.wikipedia.org/wiki/List_of_U.S._states_by_population_density 
popdensity = { 
'New Jersey': 438.00, 
'Rhode Island': 387.35, 
'Massachusetts': 312.68, 
'Connecticut': 271.40, 
'Maryland': 209.23, 
'New York': 155.18, 
'Delaware': 154.87, 
'Florida':  114.43, 
'Ohio': 107.05, 
'Pennsylvania': 105.80, 
'Illinois': 86.27, 
'California': 83.85, 
'Hawaii': 72.83, 
'Virginia': 69.03, 
'Michigan': 67.55, 
'Indiana': 65.46, 
'North Carolina': 63.80, 
'Georgia':  54.59, 
'Tennessee': 53.29, 
'New Hampshire': 53.20, 
'South Carolina': 51.45, 
'Louisiana': 39.61, 
'Kentucky': 39.28, 
'Wisconsin': 38.13, 
'Washington': 34.20, 
'Alabama':  33.84, 
'Missouri': 31.36, 
'Texas': 30.75, 
'West Virginia': 29.00, 
'Vermont':  25.41, 
'Minnesota': 23.86, 
'Mississippi': 23.42, 
'Iowa': 20.22, 
'Arkansas': 19.82, 
'Oklahoma': 19.40, 
'Arizona':  17.43, 
'Colorado': 16.01, 
'Maine': 15.95, 
'Oregon': 13.76, 
'Kansas': 12.69, 
'Utah': 10.50, 
'Nebraska': 8.60, 
'Nevada': 7.03, 
'Idaho': 6.04, 
'New Mexico': 5.79, 
'South Dakota': 3.84, 
'North Dakota': 3.59, 
'Montana':  2.39, 
'Wyoming':  1.96, 
'Alaska':  0.42} 
# choose a color for each state based on population density. 
colors={} 
statenames=[] 
cmap = plt.cm.hot # use 'hot' colormap 
vmin = 0; vmax = 450 # set range. 
for shapedict in m.states_info: 
    statename = shapedict['NAME'] 
    # skip DC and Puerto Rico. 
    if statename not in ['District of Columbia','Puerto Rico']: 
     pop = popdensity[statename] 
     # calling colormap with value between 0 and 1 returns 
     # rgba value. Invert color range (hot colors are high 
     # population), take sqrt root to spread out colors more. 
     colors[statename] = cmap(1.-np.sqrt((pop-vmin)/(vmax-vmin)))[:3] 
    statenames.append(statename) 
# cycle through state names, color each one. 
ax = plt.gca() # get current axes instance 
for nshape,seg in enumerate(m.states): 
    # skip DC and Puerto Rico. 
    if statenames[nshape] not in ['District of Columbia','Puerto Rico']: 
     color = rgb2hex(colors[statenames[nshape]]) 
     poly = Polygon(seg,facecolor=color,edgecolor=color) 
     ax.add_patch(poly) 
plt.title('Filling State Polygons by Population Density') 
plt.show() 

回答

12

任何有兴趣,我可以自己修复。每个段(阿拉斯加和夏威夷)的(x,y)坐标应该被翻译。在翻译之前,我还将阿拉斯加缩小到35%。

for循环的第二个应该被修改如下:

for nshape,seg in enumerate(m.states): 
    # skip DC and Puerto Rico. 
    if statenames[nshape] not in ['Puerto Rico', 'District of Columbia']: 
    # Offset Alaska and Hawaii to the lower-left corner. 
     if statenames[nshape] == 'Alaska': 
     # Alaska is too big. Scale it down to 35% first, then transate it. 
      seg = list(map(lambda (x,y): (0.35*x + 1100000, 0.35*y-1300000), seg)) 
     if statenames[nshape] == 'Hawaii': 
      seg = list(map(lambda (x,y): (x + 5100000, y-900000), seg)) 

     color = rgb2hex(colors[statenames[nshape]]) 
     poly = Polygon(seg,facecolor=color,edgecolor=color) 
     ax.add_patch(poly) 

这里是美国新映射(使用“绿色”颜色表)。

enter image description here

4

以上的答案是伟大的,对我来说是非常有帮助的。

我注意到有很多小岛延伸到夏威夷8个主要岛屿之外许多英里。这些在亚利桑那州,加利福尼亚州和俄勒冈州(或内华达州和爱达荷州)创造了小点,取决于您如何翻译夏威夷。要除去这些,你需要在多边形区域的一个条件。通过states_info对象做一个循环是有帮助的:

# Hawaii has 8 main islands but several tiny atolls that extend for many miles. 
# This is the area cutoff between the 8 main islands and the tiny atolls. 
ATOLL_CUTOFF = 0.005 

m = Basemap(llcrnrlon=-121,llcrnrlat=20,urcrnrlon=-62,urcrnrlat=51, 
    projection='lcc',lat_1=32,lat_2=45,lon_0=-95) 

# load the shapefile, use the name 'states' 
m.readshapefile('st99_d00', name='states', drawbounds=True) 

ax = plt.gca() 


for i, shapedict in enumerate(m.states_info): 
    # Translate the noncontiguous states: 
    if shapedict['NAME'] in ['Alaska', 'Hawaii']: 
     seg = m.states[int(shapedict['SHAPENUM'] - 1)] 
     # Only include the 8 main islands of Hawaii so that we don't put dots in the western states. 
     if shapedict['NAME'] == 'Hawaii' and float(shapedict['AREA']) > ATOLL_CUTOFF: 
      seg = list(map(lambda (x,y): (x + 5200000, y-1400000), seg)) 
     # Alaska is large. Rescale it. 
     elif shapedict['NAME'] == 'Alaska': 
      seg = list(map(lambda (x,y): (0.35*x + 1100000, 0.35*y-1300000), seg)) 
     poly = Polygon(seg, facecolor='white', edgecolor='black', linewidth=.5) 
     ax.add_patch(poly) 
+0

这太棒了!感谢您分享您的改进。 – MomoPP