參考教材
<Python編程——從入門到實踐> chapter16 數據可視化
引言
在第二小節(jié)里面,我們學習并繪制了一張世界人口分布圖,但是在提取相關數據時菌赖,我們發(fā)現梅肤,由于格式不規(guī)范司蔬,原始數據中的很多地區(qū)并沒有相應的國別碼,在這個練習中姨蝴,我們需要盡量改善這個問題......
原題
本節(jié)制作人口地圖時俊啼,對于大約12個國家,程序不能自動確定其兩個字母的國別碼左医,請找出這些古歐家授帕,在字典 COUNTRIES 中找到他們的國別碼,然后對于每個這樣的國家浮梢,都在原代碼中添加一個if-elif代碼塊跛十,用于返回其國別碼
開始!
嘖嘖嘖秕硝,才12個國家芥映,手工添加也不是很多嘛!但是远豺,根據上一節(jié)被坑的經驗奈偏,我們還是來看一看到底找不到國別碼的地區(qū)有多少個好了
先小小地修改一下代碼, 把有問題的地區(qū)先存到列表 err_country 中
for pop_dict in pop_data:
if pop_dict['Year'] == '2010':
country_name = pop_dict['Country Name']
population = int(float(pop_dict['Value']))
code = get_country_code(country_name)
if code:
cc_population[code] = population
if code == None:
err_country.append(country_name)
err_pop.append(population)
print(err_country)
看一看結果:
(ノ=Д=)ノ┻━┻ 這么多的問題地區(qū)是什么情況!Gぁ>础!
好吧棺滞,事已至此裁蚁,我們想想怎么用代碼解決這個問題
先觀察一下這個 err_country 列表
我們發(fā)現在 'World' 這個詞之前,都是一些一眼就能看出不是國家的元素
先把它們全都刪掉再說继准!
先貼代碼:
err_pop = []
key = True
for pop_dict in pop_data:
if pop_dict['Year'] == '2010':
country_name = pop_dict['Country Name']
population = int(float(pop_dict['Value']))
code = get_country_code(country_name)
if code:
cc_population[code] = population
if (code == None) and (key == False):
err_country.append(country_name)
err_pop.append(population)
if country_name == 'World':
key = False
用一個 key 來檢測是否讀取到了 'World'枉证,只有在 'World‘ 之后的元素才被存進 列表 err_country 中,同時锰瘸, 我們用一個列表 err_pop 來儲存對應的人口信息
運行一下:
很好刽严!前面那些太明顯的地名已經沒了
在 COUNTRIES 字典中找到對應的國別碼
雖然剔除了很多信息,但是剩下的地名依然很多,還是要依靠代碼找到他們對應的國別碼
分析一下
程序之所以找不到這些地名對應的國別碼舞萄,是因為它們的名字跟字典 COUNTRIES 里的標準名稱不匹配眨补,要解決這個問題,一個簡單的思路是 我們只提取 這些地名的部分單詞作為關鍵字倒脓,然后用這些關鍵字去跟字典 COUNTRIES 進行匹配撑螺, 可以觀察到,大部分的地名的關鍵字都在 第一個單詞崎弃,少數以 'St.' 開頭的地名 關鍵字在 'St.' 后的第一個單詞
這樣甘晤,大致的思路就出來了
思路:提取關鍵字-> 匹配字典->加上人口信息做成新的字典
step 1: 關鍵字的提取
很簡單,對于每一個 'err_country' 里的字符串元素饲做,從第個字符開始查找點號 '.'线婚, 空格 ' ' ,還有逗號 ',',一旦找到就停下來盆均,把之前的字符存在新的字符串中塞弊,可以用兩個循環(huán)實現,我們把這個功能做成一個函數:
def get_first_word(name):
new_name = ''
for letter in name:
new_name += letter
if letter == ','or letter == ' ' or letter == '.':
new_name = new_name[:-1] #刪掉最后的 , 空格 或者 .
break
return new_name
step 2: 匹配字典
一樣依靠兩個循環(huán)實現泪姨,這里比較麻煩的是要把儲存人口數據的 'err_pop' 里面的數據 對應地 放到新字典里面游沿,本人沒什么好方法,用了最笨的計數法肮砾,在歷遍 err_country 的同時诀黍, 用 count 控制 err_pop 保持同步
def get_pop(filename):
--snip--
new_country = {}
count = -1
for err_country in new_err:
count += 1
for code , country in COUNTRIES.items():
if err_country in country:
new_country[code] = err_pop[count]
--snip--
step 3:合成一個新的字典
這一步算是最簡單的了,不廢話仗处,直接上
for code, pop in new_country.items():
cc_population[code] = pop
完整的代碼在這里
#! /usr/bin/python <br> # -*- coding: utf8 -*-
import json
from country_codes import get_country_code
import string as s
from pygal.maps.world import COUNTRIES
def get_first_word(name):
new_name = ''
for letter in name:
new_name += letter
if letter == ','or letter == ' ' or letter == '.':
new_name = new_name[:-1] #刪掉最后的 , 空格 或者 .
break
return new_name
def get_pop(filename):
filename = 'population_data.json'
cc_population = {}
err_country = []
with open(filename) as f:
pop_data = json.load(f)
err_pop = []
key = True
for pop_dict in pop_data:
if pop_dict['Year'] == '2010':
country_name = pop_dict['Country Name']
population = int(float(pop_dict['Value']))
code = get_country_code(country_name)
if code:
cc_population[code] = population
if (code == None) and (key == False):
err_country.append(country_name)
err_pop.append(population)
if country_name == 'World':
key = False
print(err_country)
new_err = []
for country_name in err_country:
new_name = get_first_word(country_name)
if new_name == 'St':
new_name = country_name[4:]
new_name = get_first_word(new_name)
new_err.append(new_name)
new_country = {}
count = -1
for err_country in new_err:
count += 1
for code , country in COUNTRIES.items():
if err_country in country:
new_country[code] = err_pop[count]
for code, pop in new_country.items():
cc_population[code] = pop
return cc_population
然后繪圖文件那里也要做相應的修改眯勾,很簡單,直接貼完整的代碼好了
#! /usr/bin/python <br> # -*- coding: utf8 -*-
import pygal
import json
from country_codes import get_country_code
from pygal.style import RotateStyle
from pygal.style import LightColorizedStyle
from countries import get_pop
#將數據加載到一個列表中
filename = 'population_data.json'
#創(chuàng)建一個包含人口數量的字典
cc_population = {}
cc_pop1,cc_pop2,cc_pop3 = {},{},{}
cc_population = get_pop(filename)
for cc,pop in cc_population.items():
if pop < 10000000:
cc_pop1[cc] = pop
elif pop < 1000000000:
cc_pop2[cc] = pop
else:
cc_pop3[cc] = pop
wm_style = RotateStyle('#226699',base_style=LightColorizedStyle)
wm = pygal.maps.world.World(style=wm_style)
wm.title = 'World Population in 2010, by Country'
wm.add('0-10m',cc_pop1)
wm.add('10m-1bn',cc_pop2)
wm.add('>1bn',cc_pop3)
wm.render_to_file('world_population_v10.svg')
上一張成果圖
比較一下之前的
給自己鼓個掌=帷V渚O庵?醯怠!歇拆!
PS: 總結
其實還是有沒有統(tǒng)計進去的鞋屈,但是臣妾已經盡力了,如果在提取關鍵詞的時候多提取幾個應該就可以把更多的地區(qū)統(tǒng)計進來