寫在之前
選自《Python編程從入門到實踐》
正式開始
生成數據
對於密集的數據,只是簡單直觀的觀察無法明白其含義,而通過類似於圖表方式呈現數據便於理解含義
Python中的Matplotlib用於製作簡單的圖表,例如折線圖以及散點圖
Pygal專注於生成適合在數字設備顯示的圖表。通過使用Pygal,可在用戶與圖標交互時突出元素以及調整其大小,還可以輕鬆地調整整個圖表的尺寸,使其適合在不同設備上顯示。
Matplotlib
展示使用Matplotlib來繪製一個折線圖
# 導入matplotlib中的pyplot模塊,利用其中的工具進行操作
import matplotlib.pyplot as plt
# 接下來的兩個列表分別對應橫縱座標的數據
InPut=[1,2,3,4,5]
list=[238,3878,2387,3478,278]
plt.plot(InPut,list,linewidth=7.5) #繪製折線圖的函數 傳遞橫縱座標以及線的粗細
plt.title("Square NumBers",fontsize=10) #繪製主標題以及標題字號大小
plt.xlabel("Cdy is X",fontsize=10) #繪製橫座標標題以及標題字號大小
plt.ylabel("Wzy is Y",fontsize=10) #繪製縱座標標題以及標題字號大小
plt.tick_params(axis='both',labelsize=15) #修改座標軸上標記字號的大小,‘both’表示都修改
plt.show() #打開matplotlib查看器,顯示繪製的圖表
效果如下(單擊磁盤圖標可用於保存):
除了折線圖之外 還可以繪製散點圖
import matplotlib.pyplot as plt
x_values=[]
y_values=[]
# 繪製一個[1,21,41,...]的平方分佈的散點圖
for i in range(1,1001,20):
x_values.append(i)
y_values.append(i**2)
# 後三個分別是點的顏色 點邊緣的顏色 點的大小
plt.scatter(x_values,y_values,c="red",edgecolor="green",s=15)
# 同上
plt.xlabel("Cdy is X",fontsize=20)
plt.ylabel("Wzy is Y",fontsize=20)
# plt.savefig("Picture1.png",bbox_inches="tight")
# 將生成的散點圖保存在同一文件目錄下的圖片中
plt.savefig("Picture1.png")
效果如下:
保存在本地文件夾:
Pygal
這裏模擬的是擲一個色子1000次 然後繪製直方圖來顯示不同點數的出現次數分佈
from random import randint
import pygal
# 一個用於模擬單次隨機擲色子的點數的類
class Die():
def __init__(self,num_sides=6):
self.num_sides=num_sides
def roll(self):
return randint(1,self.num_sides)
die=Die()
results=[]
frequencies=[]
# 收集1000次的結果
for roll_num in range(1,1000):
result=die.roll()
results.append(result)
# 收集1000次中不同點數出現的次數
for value in range(1,die.num_sides+1):
frequency=results.count(value)
frequencies.append(frequency)
# 爲了創建條形圖 我們創建了一個pygal.Bar()的實例,並將其存儲在hist中
hist=pygal.Bar()
# 標題
hist.title="Our Results of Rolling One D6"
# 橫座標軸
hist.x_lables=['1','2','3','4','5','6']
# 使用add將一系列值添加到圖表中,'D6'表示標籤也就是圖例
hist.add('D6',frequencies)
# 存儲在一個文件中,文件名爲
hist.render_to_file('die_visual.svg')
效果如下(我們把光標移到對應的條形上面之後,顯示具體數字,體現交互性):
生成的文件位於同一文件目錄中:
下載數據
對於數據可視化,很大一部分都是可視化從網上下載的龐大複雜的數據
這裏處理的是兩種比較常見的數據存儲格式:CSV以及JSON
CSV
文本文件中存儲數據最簡單的就是將數據作爲一系列以逗號分隔的值(CSV)作爲文件
例如:
2983,238478,3802387,2378-238-2387,-2378,...,23878,238478,,238478
對於人而言 閱讀起來非常麻煩 但是對於程序而言 這有助於加快數據分析過程
接下來對於保存在一個csv格式文件裏的阿拉斯加錫特卡天氣數據進行分析
首先是分析csv文件頭
# 導入csv模塊
import csv
filename="sitka_weather_07-2014.csv"
# 打開文件並將結果文件對象存儲在f中
with open(filename) as f:
#調用csv.reader()創建一個與該文件相關的閱讀器(reader)
#這裏的話我把reader理解爲一個指針 指向當前的一行
reader=csv.reader(f)
#next表示返回調用文件(reader)的下一行
header_now=next(reader)
print(header_now)
效果如下:
在具體打印某一列的數據:
import csv
filename="sitka_weather_07-2014.csv"
with open(filename) as f:
reader=csv.reader(f)
header_now=next(reader)
highs=[]
# 從reader當前指向一行向下不斷枚舉 反覆提取第0列
for row in reader:
highs.append(row[0])
print(highs)
效果如下:
提取數據完成之後,我們來利用提取的數據繪製氣溫折線圖:
import csv
from datetime import datetime
from matplotlib import pyplot as plt
filename="sitka_weather_2014.csv"
highs=[]
dates=[]
lows=[]
with open(filename) as f:
reader=csv.reader(f)
header_now=next(reader)
for row in reader:
current_date=datetime.strptime(row[0],"%Y-%m-%d")
#利用python提供的datetime工具來處理日期
dates.append(current_date)
high=int(row[1])
highs.append(high)
low=int(row[3])
lows.append(low)
# 調整顯示屏幕尺寸
fig=plt.figure(dpi=128,figsize=(10,6))
# 分別畫兩條不同顏色的折線來表示高低溫
plt.plot(dates,highs,c="blue")
plt.plot(dates,lows,c="red")
# 中間填充色
plt.fill_between(dates,highs,lows,facecolor='blue',alpha=0.1)
# 繪製傾斜標籤
fig.autofmt_xdate()
plt.show()
效果如下:
但是我們不能保證我們的數據沒有半分紕漏
比如說我們的示例文件之中存在數據缺失
所以我們需要來一個檢查機制來對數據進行篩查 防止出現數據缺失造成的錯誤
import csv
from datetime import datetime
from matplotlib import pyplot as plt
filename="death_valley_2014.csv"
highs=[]
dates=[]
lows=[]
with open(filename) as f:
reader=csv.reader(f)
header_now=next(reader)
for row in reader:
try:
current_date=datetime.strptime(row[0],"%Y-%m-%d")
high=int(row[1])
low=int(row[3])
# 一個特殊的異常類型 數據缺失 打印出缺失的日期
except ValueError:
print(current_date,"missing_date")
else:
dates.append(current_date)
highs.append(high)
lows.append(low)
fig=plt.figure(dpi=128,figsize=(10,6))
tot=len(dates)
plt.plot(dates,highs,c="blue")
plt.plot(dates,lows,c="red")
plt.fill_between(dates,highs,lows,facecolor='blue',alpha=0.1)
fig.autofmt_xdate()
plt.show()
效果如下:
JSON
JSON同樣是數據存儲的格式之一
我們提取json格式的數據並利用pygal來處理 這裏展示的根據世界人口數據來生成世界人口地圖
首先 提取json格式的數據
import json
filename="population_data.json"
with open(filename) as f:
pop_data=json.load(f)
#將其中的數據導入到一個列表中
for pop_dict in pop_data:
if pop_dict["Year"]=='2010':
country_name=pop_dict["Country Name"]
population=int(float(pop_dict["Value"]))
print(country_name+" : "+str(population))
效果如下:
其次 生成一個簡單,美洲的的地圖
# pygal自己提供了一個地圖製作工具
import pygal.maps.world
wm = pygal.maps.world.World()
wm.title="North,Central,and South America"
# add()前者是標籤 後者是利用python的國別碼來代表國家的列表
wm.add('North America',['ca','mx','us'])
wm.add('Central America',['bz','cr','gt','hn','ni','pa','sv'])
wm.add('South America',['ar','bo','br','cl','co','ec','gf','gy','pe','py','sr','uy','ve'])
wm.render_to_file("americas.svg")
效果如下:
接下來 按照2010年的人口數據來製作世界人口分佈地圖
import json
import pygal
from pygal.style import RotateStyle
from pygal.style import LightColorizedStyle
import pygal.maps.world
from country_codes import get_country_code
filename="population_data.json"
with open(filename) as f:
pop_data=json.load(f)
# 把上面傳遞的列表替換成了字典
# 這樣的話add函數會自動根據字典value的值來決定顏色深淺
world_population={}
for pop_dict in pop_data:
if pop_dict["Year"]=="2010":
country=pop_dict["Country Name"]
population=int(float(pop_dict["Value"]))
code=get_country_code(country)
if code:
world_population[code]=population
#利用顏色編碼設置基本顏色 後者LightColorizedStyle是加亮
wm=pygal.maps.world.World(style=RotateStyle("#336699",base_style=LightColorizedStyle))
wm.add('2010',world_population)
wm.render_to_file("World_Population.svg")
效果如下:
可以很明顯的發現 對於數據來講 由於特殊數據(中國,印度的人口)的存在 導致了直觀感覺不是很好
所以我們接下來進行一個簡單的分組(010^7,10^7109,大於109)
import json
import pygal
from pygal.style import RotateStyle
from pygal.style import LightColorizedStyle
import pygal.maps.world
from country_codes import get_country_code
filename="population_data.json"
with open(filename) as f:
pop_data=json.load(f)
world_population={}
for pop_dict in pop_data:
if pop_dict["Year"]=="2010":
country=pop_dict["Country Name"]
population=int(float(pop_dict["Value"]))
code=get_country_code(country)
if code:
world_population[code]=population
cc_pops_1={}
cc_pops_2={}
cc_pops_3={}
for cc,pop in world_population.items():
if pop<10000000:
cc_pops_1[cc]=pop
elif pop<1000000000:
cc_pops_2[cc]=pop
else:
cc_pops_3[cc]=pop
wm=pygal.maps.world.World(style=RotateStyle("#336699",base_style=LightColorizedStyle))
wm.title="2010 World Population"
# 打上分組的標籤 分別傳遞三個不同的字典
wm.add('0-10m',cc_pops_1)
wm.add('10m-1bn',cc_pops_2)
wm.add('>1bn',cc_pops_3)
wm.render_to_file("World_Population1.svg")
效果如下:
API
通過Web應用編程接口(API) 我們可以編寫一個獨立的程序自動請求網站的特定信息而不是整個網頁,在對這些信息進行可視化
這樣做的好處是我們始終通過最新的網頁生成可視化數據,呈現出來的信息也是最新的
演示的可視化基於GitHub的信息
https://api.github.com/search/repositories?q=language:python&sort=stars
這是一個返回GitHub當前託管了多少個Python項目的調用 以及當前最受歡迎的Python倉庫的信息
https://api.github.com/ 表示發送請求到GitHub網站中相應API調用的部分
search/repositories 讓API搜索GitHub所有的倉庫
其後問號? 表示我們要傳遞一個實參
q表示查詢
language:python 表示我們只要主要語言爲Python的倉庫的信息
&sort=stars 指定將項目按其獲得的星級進行排序
我們可以發現 這個並不適合人工輸入
所以 我們需要編寫程序 使得其不需要人工輸入 而是自動讀取並處理
這裏是找到GitHub上星級最高的Python項目
# 導入requests 使得程序可以輕鬆地向網站請求信息以及檢查返回的響應
import requests
# 執行API調用並存儲響應
URL="https://api.github.com/search/repositories?q=language:python&sort=stars"
r=requests.get(URL)
print("Status code:",r.status_code) #覈實調用是否成功 成功時狀態碼爲200
response_dict=r.json() # 使用json()方法將其json格式轉化爲字典
print("Total repositories:",response_dict["total_count"])
dict=response_dict["items"]
# 提取打印我們所要的值
for x in dict:
print("\nName is ",x["name"])
print("Owner is ",x["owner"]["login"])
print("Stars is ",x["stargazers_count"])
print("Repository is",x["html_url"])
print("Description is ",x["description"])
接下來 我們使用Pygal圖表來根據API所獲取的數據 創建一個交互式條形圖:條形的高低表示項目獲得了多少顆星
import requests
import pygal
from pygal.style import LightColorizedStyle as LCS,LightenStyle as LS
URL="https://api.github.com/search/repositories?q=language:python&sort=stars"
r=requests.get(URL)
print("Status code:",r.status_code)
response_dict=r.json()
print("Total repositories:",response_dict["total_count"])
dict=response_dict["items"]
names,stars=[],[]
# 數據提取操作
for x in dict:
names.append(x['name'])
stars.append(x['stargazers_count'])
#創建顏色格式 前者爲基本顏色編碼 後者爲加亮
my_style=LS("#336699",base_style=LCS)
# style是傳遞顏色格式 x_label_rotation設值橫座標的旋轉角度 show_legend爲是否展示圖例
chart=pygal.Bar(style=my_style,x_label_rotation=45,show_legend=False)
chart.title="Most-Starrted Python Projects on GitHub"
chart.x_labels=names
#對於數據添加標籤
chart.add('xkj',stars)
#保存
chart.render_to_file('python_Pygal.svg')
效果如下:
爲了獲得更好的體驗 我們引入了自定義工具
類似於之前 我們將chart.add('',stars)
中由傳遞列表該爲傳遞字典
在字典中除了已有的星級之外 還會有對應的表述以及相應的鏈接
import requests
import pygal
from pygal.style import LightColorizedStyle as LCS,LightenStyle as LS
URL="https://api.github.com/search/repositories?q=language:python&sort=stars"
r=requests.get(URL)
print("Status code:",r.status_code)
response_dict=r.json()
print("Total repositories:",response_dict["total_count"])
dict=response_dict["items"]
names,stars=[],[]
for x in dict:
names.append(x['name'])
stars_tmp={
"value":x["stargazers_count"],
"label":str(x["description"]),
"xlink":x["html_url"]
}
stars.append(stars_tmp)
my_style=LS("#336699",base_style=LCS)
chart=pygal.Bar(style=my_style,x_label_rotation=45,show_legend=False)
chart.title="Most-Starrted Python Projects on GitHub"
chart.x_labels=names
chart.add('xkj',stars)
chart.render_to_file('python_Pygal.svg')
效果如下:
總結
這就是目前的所做的全部了