Skip to main content
 首页 » 编程设计

Python: Bokeh 未按预期生成世界国家 map

2025年05月04日28虾米哥

我正在尝试生成按某些值着色的世界国家 map ,但生成的 map 中缺少某些国家/地区。这是我的代码:

获取geojson数据

import urllib 
url = 'https://raw.githubusercontent.com/datasets/geo-boundaries-world-110m/master/countries.geojson' 
testfile = urllib.URLopener() 
if os.path.exists('countries.json'): 
    print "file already exists" 
else: 
    testfile.retrieve(url, "countries.json") 

使用 Bokeh 生成 map

import json,pandas 
from collections import OrderedDict 
from bokeh.plotting import figure, show, output_file, ColumnDataSource 
from bokeh.models import HoverTool 
user_by_country_count = pandas.read_csv('data.csv') 
 
with open('countries.json','r') as f: 
    geodata = json.load(f) 
f.close() 
geodata_features = geodata['features'] 
country_xs = [] 
country_ys = [] 
country_names = [] 
country_num_users = [] 
country_colors = [] 
colors = ['#CCE5FF','#CCCCFF','#9999FF','#6666FF','#3333FF', 
         '#0000FF','#0000CC','#000099','#000066','#0000CC'] 
 
for aCountry in geodata_features: 
    coords = aCountry['geometry']['coordinates'][0] 
    country_xs.append(map(lambda x:x[0],coords)) 
    country_ys.append(map(lambda x:x[1],coords)) 
    cName = aCountry['properties']['name'] 
    country_names.append(cName) 
    if cName in user_by_country_count['Country'].values:             
        num_users = user_by_country_count['Count'][user_by_country_count[user_by_country_count.Country==cName].index[0]] 
        country_num_users.append(num_users) 
        country_colors.append(colors[int(np.log(num_users))]) 
    else: 
        country_num_users.append(0) 
        country_colors.append("#00FF80") 
source = ColumnDataSource( 
    data = dict( 
        x=country_xs, 
        y=country_ys, 
        color=country_colors, 
        name=country_names, 
        users=country_num_users, 
    ) 
) 
output_file("global.html", title="global.py example") 
TOOLS="pan,wheel_zoom,box_zoom,reset,hover,save" 
p = figure(title="Upwork Users Location", tools=TOOLS) 
p.patches('x', 'y', 
    fill_color='color', fill_alpha=0.7, 
    line_color="white", line_width=0.5, 
    source=source) 
hover = p.select(dict(type=HoverTool)) 
hover.point_policy = "follow_mouse" 
hover.tooltips = OrderedDict([ 
    ("Name", "@name"), 
    ("Number of Users", "@users"), 
]) 
show(p) 

我怀疑问题可能出在 geojson 数据中。当我仔细观察时,看起来有些坐标是作为数字列表给出的,而另一些坐标是作为数字列表给出的。但是这个 geojson 以前被很多人使用过,所以我想知道是否有人会遇到类似的问题。

请您参考如下方法:

阿根廷和其他一些国家属于MultiPolygon 类型,例如巴西属于Polygon 类型。拥有岛屿或独立土地的国家属于 MultiPolygon 类型。所以 MultiPolygon 的坐标应该包含更多一级数组,你应该处理它:

#!/usr/bin/python2 
import json,pandas 
from collections import OrderedDict 
from bokeh.plotting import figure, show, output_file, ColumnDataSource 
from bokeh.models import HoverTool 
import math 
user_by_country_count = pandas.read_csv('data.csv') 
 
with open('countries.json','r') as f: 
    geodata = json.load(f) 
 
geodata_features = geodata['features'] 
country_xs = [] 
country_ys = [] 
country_names = [] 
country_num_users = [] 
country_colors = [] 
colors = ['#CCE5FF','#CCCCFF','#9999FF','#6666FF','#3333FF', 
         '#0000FF','#0000CC','#000099','#000066','#0000CC'] 
 
for aCountry in geodata_features: 
    cName = aCountry['properties']['name'] 
    country_names.append(cName) 
 
    geometry_type = aCountry['geometry']['type'] 
    if geometry_type == "MultiPolygon": 
        for poly_coords in aCountry['geometry']['coordinates']: 
            coords = poly_coords[0] 
 
            country_xs.append(map(lambda x:x[0],coords)) 
            country_ys.append(map(lambda x:x[1],coords)) 
    else: 
        coords = aCountry['geometry']['coordinates'][0] 
        country_xs.append(map(lambda x:x[0],coords)) 
        country_ys.append(map(lambda x:x[1],coords)) 
 
    if cName in user_by_country_count['Country'].values: 
        num_users = user_by_country_count['Count'][user_by_country_count[user_by_country_count.Country==cName].index[0]] 
        country_num_users.append(num_users) 
        country_colors.append(colors[int(math.log(num_users))]) 
    else: 
        country_num_users.append(0) 
        country_colors.append("#00FF80") 
 
source = ColumnDataSource( 
    data = dict( 
        x=country_xs, 
        y=country_ys, 
        color=country_colors, 
        name=country_names, 
        users=country_num_users, 
    ) 
) 
output_file("global.html", title="global.py example") 
TOOLS="pan,wheel_zoom,box_zoom,reset,hover,save" 
p = figure(title="Upwork Users Location", tools=TOOLS) 
p.patches('x', 'y', 
    fill_color='color', fill_alpha=0.7, 
    line_color="white", line_width=0.5, 
    source=source) 
hover = p.select(dict(type=HoverTool)) 
hover.point_policy = "follow_mouse" 
hover.tooltips = OrderedDict([ 
    ("Name", "@name"), 
    ("Number of Users", "@users"), 
]) 
show(p)