Python 數據可視化利器
(給
Python開發者
加星標,提升Python技能
)
作者:
zone7
(本文來自作者投稿,簡介見末尾)
概述
前言
推薦
plotly
bokeh
pyecharts
後記
前言
前段時間有讀者向我反映,想看看數據可視化方面的文章,這不?現在就開始寫了,如果你想看哪些方面的文章,可以通過留言或者後台告訴我。數據可視化的第三方庫挺多的,這裡我主要推薦兩個,分別是 bokeh、pyecharts。
如果我的文章對你有幫助,歡迎關注、點贊、轉發,這樣我會更有動力做原創分享。
推薦
數據可視化的庫有挺多的,這裡推薦幾個比較常用的:
Matplotlib
Plotly
Seaborn
Ggplot
Bokeh
Pyechart
Pygal
Plotly
plotly 文檔地址(https://plot.ly/python/#financial-charts)
使用方式:
plotly 有 online 和 offline 兩種方式,這裡只介紹 offline 的。
這是 plotly 官方教程的一部分
import as import as False "#00CED1" 6 # 配置線寬和顏色
data = [dict(
visible=
line=dict(color=
name=
"?? = "
+ str(step),x=np.arange(
0
,10
,0.01
),# x 軸參數
y=np.sin(step * np.arange(
0
,10
,0.01
)))for
stepin
np.arange(
0
,5
,0.1
)]# y 軸參數
data[
10
]["visible"
] =True
py.iplot(data, filename=
"Single Sine Wave"
)只要將最後一行中的
py .iplot
替換為下面代碼
py .offline.plot
便可以運行。
漏斗圖
這個圖代碼太長了,就不 po 出來了。
Basic Box Plot
好吧,不知道怎麼翻譯,直接用原名。
import plotly.plotly
import plotly.graph_objs as go
import numpy as np
y0 = np.random.randn(50)-1
y1 = np.random.randn(50)+1
trace0 = go.Box(
y=y0
)
trace1 = go.Box(
y=y1
)
data = [trace0, trace1]
plotly.offline.plot(data)
Wind Rose Chart
好吧,不知道怎麼翻譯,直接用原名。
import go
trace1 =
go
.Barpolar(r=[
77.5
,72.5
,70.0
,45.0
,22.5
,42.5
,40.0
,62.5
],text=[
"North"
,"N-E"
,"East"
,"S-E"
,"South"
,"S-W"
,"West"
,"N-W"
],name=
"11-14 m/s"
,marker=dict(
color=
"rgb(106,81,163)"
)
)
trace2 =
go
.Barpolar(r=[
57.49999999999999
,50.0
,45.0
,35.0
,20.0
,22.5
,37.5
,55.00000000000001
],text=[
"North"
,"N-E"
,"East"
,"S-E"
,"South"
,"S-W"
,"West"
,"N-W"
], # 滑鼠浮動標籤文字描述name=
"8-11 m/s"
,marker=dict(
color=
"rgb(158,154,200)"
)
)
trace3 =
go
.Barpolar(r=[
40.0
,30.0
,30.0
,35.0
,7.5
,7.5
,32.5
,40.0
],text=[
"North"
,"N-E"
,"East"
,"S-E"
,"South"
,"S-W"
,"West"
,"N-W"
],name=
"5-8 m/s"
,marker=dict(
color=
"rgb(203,201,226)"
)
)
trace4 =
go
.Barpolar(r=[
20.0
,7.5
,15.0
,22.5
,2.5
,2.5
,12.5
,22.5
],text=[
"North"
,"N-E"
,"East"
,"S-E"
,"South"
,"S-W"
,"West"
,"N-W"
],name=
"< 5 m/s"
,marker=dict(
color=
"rgb(242,240,247)"
)
)
data = [trace1, trace2, trace3, trace4]
layout =
go
.Layout(title=
"Wind Speed Distribution in Laurel, NE"
,font=dict(
size=
16
),
legend=dict(
font=dict(
size=
16
)
),
radialaxis=dict(
ticksuffix=
"%"
),
orientation=
270
)
fig =
go
.Figure(data=data, layout=layout)plotly.offline.plot(fig, filename=
"polar-area-chart"
)Basic Ternary Plot with Markers
篇幅有點長,這裡就不 po 代碼了。
Bokeh
這裡展示一下常用的圖表和比較搶眼的圖表,詳細的文檔可查看(https://bokeh.pydata.org/en/latest/docs/user_guide/categorical.html)
條形圖
這配色看著還挺舒服的,比 pyecharts 條形圖的配色好看一點。
show from import from import from import "colormapped_bars.html" # 配置輸出文件名 "Apples" "魅族" "OPPO" "VIVO" "小米" "華為" # 數據 5 3 4 2 4 6 # 數據 source data 0 9 250 "Fruit Counts" None "" # 條形圖配置項 "fruits" "counts" 0.9 "color" "fruits" source source None # 配置網格線顏色 "horizontal" # 圖表方向為水平方向 "top_center" show # 展示圖表from bokeh.io import
output_file(
fruits = [
counts = [
p = figure(x_range=fruits, y_range=(
toolbar_location=
p.vbar(x=
p.xgrid.grid_line_color =
p.legend.orientation =
p.legend.location =
年度條形圖
可以對比不同時間點的量。
show from import from import "bars.html" # 輸出文件名 "Apple" "魅族" "OPPO" "VIVO" "小米" "華為" # 參數 years "2015" "2016" "2017" # 參數 data "fruits" "2015" 2 1 4 3 2 4 "2016" 5 3 3 2 4 6 "2017" 3 2 4 4 5 3 year for in for year in years sum data "2015" data "2016" data "2017" source data 250 "Fruit Counts by Year" None "" "x" "counts" 0.9 source source 0 0.1 1 None showfrom bokeh.io import
output_file(
fruits = [
x = [(fruit,
counts =
p = figure(x_range=FactorRange(*x), plot_height=
toolbar_location=
p.vbar(x=
p.y_range.start =
p.x_range.range_padding =
p.xaxis.major_label_orientation =
p.xgrid.grid_line_color =
餅圖
show from import from import from import "pie.html" "中國" 157 "美國" 93 "日本" 89 "巴西" 63 "德國" 44 "印度" 42 "義大利" 40 "澳大利亞" 35 "法國" 31 "西班牙" 29 data "index" index str columns 0 "value" "index" "country" data "angle" data "value" sum 2 pi data "color" len 350 "Pie Chart" None "hover" "@country: @value" 0 1 0.4 "angle" True "angle" "white" "color" "country" source data None False None showfrom collections import Counter
from math import pi
import pandas as pd
from bokeh.io import output_file,
output_file(
x = Counter({
})
p = figure(plot_height=
tools=
p.wedge(x=
start_angle=cumsum(
line_color=
p.axis.axis_label=
p.axis.visible=
p.grid.grid_line_color =
條形圖
show from import from import from import "stacked_split.html" "Apples" "Pears" "Nectarines" "Plums" "Grapes" "Strawberries" years "2015" "2016" "2017" "fruits" "2015" 2 1 4 3 2 4 "2016" 5 3 4 2 4 6 "2017" 3 2 4 4 5 3 "fruits" "2015" -1 0 -1 -3 -2 -1 "2016" -2 -1 -3 -1 -2 -2 "2017" -1 -2 -1 0 -2 -2 250 -16 16 "Fruit import/export, by year" None years "fruits" 0.9 source "%s exports" for in years years "fruits" 0.9 source "%s imports" for in years 0.1 None "top_left" None None showfrom bokeh.io import output_file,
output_file(
fruits = [
exports = {
imports = {
p = figure(y_range=fruits, plot_height=
toolbar_location=
p.hbar_stack(
legend=[
p.hbar_stack(
legend=[
p.y_range.range_padding =
p.ygrid.grid_line_color =
p.legend.location =
p.axis.minor_tick_line_color =
p.outline_line_color =
散點圖
show "line.html" 400 400 1 2 3 4 5 6 7 2 4 5 size 20 "navy" 0.5 showfrom bokeh.plotting import figure, output_file,
output_file(
p = figure(plot_width=
p.circle([
六邊形圖
這兩天,馬蜂窩剛被發現數據造假,這不,與馬蜂窩應應景。
import as from import from import from import "hex_coords.html" 0 0 0 -1 -1 1 1 0 -1 1 0 1 -1 0 400 400 None # False # 配置網格是否可見 1 "firebrick" 3 "navy" 4 "white" 0.5 1 "pointytop" "(%d, %d)" for in "middle" "center"
output_file(
q = np.array([
r = np.array([
p = figure(plot_width=
p.grid.visible =
p.hex_tile(q, r, size=
line_color=
x, y = axial_to_cartesian(q, r,
p.text(x, y, text=[
text_baseline=
show(p)
環比條形圖
這個實現挺厲害的,看了一眼就吸引了我。我在代碼中都做了一些注釋,希望對你理解有幫助。註:圓心為正中央,即直角坐標系中標籤為(0,0)的地方。
from collections import OrderedDict
from math import log, sqrt
import numpy as np
import pandas as pd
from six.moves import cStringIO as StringIO
from bokeh.plotting import figure, show, output_file
antibiotics =
"""
bacteria, penicillin, streptomycin, neomycin, gram
結核分枝桿菌, 800, 5, 2, negative
沙門氏菌, 10, 0.8, 0.09, negative
變形桿菌, 3, 0.1, 0.1, negative
肺炎克雷伯氏菌, 850, 1.2, 1, negative
布魯氏菌, 1, 2, 0.02, negative
銅綠假單胞菌, 850, 2, 0.4, negative
大腸桿菌, 100, 0.4, 0.1, negative
產氣桿菌, 870, 1, 1.6, negative
白色葡萄球菌, 0.007, 0.1, 0.001, positive
溶血性鏈球菌, 0.001, 14, 10, positive
草綠色鏈球菌, 0.005, 10, 40, positive
肺炎雙球菌, 0.005, 11, 10, positive
"""
drug_color = OrderedDict([
# 配置中間標籤名稱與顏色
(
"盤尼西林"
,"#0d3362"
),(
"鏈黴素"
,"#c64737"
),(
"新黴素"
,"black"
),])
gram_color = {
"positive"
:"#aeaeb8"
,"negative"
:"#e69584"
,}
# 讀取數據
df = pd.read_csv(StringIO(antibiotics),
skiprows=1,
skipinitialspace=True,
engine="python")
width = 800
height = 800
inner_radius = 90
outer_radius = 300 - 10
minr = sqrt(log(.001 * 1E4))
maxr = sqrt(log(1000 * 1E4))
a = (outer_radius - inner_radius) / (minr - maxr)
b = inner_radius - a * maxr
def rad(mic):
return a * np.sqrt(np.log(mic * 1E4)) + b
big_angle = 2.0 * np.pi / (len(df) + 1)
small_angle = big_angle / 7
# 整體配置
p = figure(plot_width=width, plot_height=height, title=
""
,x_axis_type=None, y_axis_type=None,
x_range=(-420, 420), y_range=(-420, 420),
min_border=0, outline_line_color=
"black"
,background_fill_color=
"#f0e1d2"
)p.xgrid.grid_line_color = None
p.ygrid.grid_line_color = None
# annular wedges
angles = np.pi / 2 - big_angle / 2 - df.index.to_series() * big_angle
#計算角度
colors = [gram_color[gram] for gram in df.gram]
# 配置顏色
p.annular_wedge(
0, 0, inner_radius, outer_radius, -big_angle + angles, angles, color=colors,
)
# small wedges
p.annular_wedge(0, 0, inner_radius, rad(df.penicillin),
-big_angle + angles + 5 * small_angle, -big_angle + angles + 6 * small_angle,
color=drug_color["盤尼西林"])
p.annular_wedge(0, 0, inner_radius, rad(df.streptomycin),
-big_angle + angles + 3 * small_angle, -big_angle + angles + 4 * small_angle,
color=drug_color["鏈黴素"])
p.annular_wedge(0, 0, inner_radius, rad(df.neomycin),
-big_angle + angles + 1 * small_angle, -big_angle + angles + 2 * small_angle,
color=drug_color["新黴素"])
# 繪製大圓和標籤
labels = np.power(10.0, np.arange(-3, 4))
radii = a * np.sqrt(np.log(labels * 1E4)) + b
p.circle(0, 0, radius=radii, fill_color=None, line_color=
"white"
)p.text(0, radii[:-1], [str(r) for r in labels[:-1]],
text_font_size=
"8pt"
, text_align="center"
, text_baseline="middle"
)# 半徑
p.annular_wedge(0, 0, inner_radius - 10, outer_radius + 10,
-big_angle + angles, -big_angle + angles, color=
"black"
)# 細菌標籤
xr = radii[0] * np.cos(np.array(-big_angle / 2 + angles))
yr = radii[0] * np.sin(np.array(-big_angle / 2 + angles))
label_angle = np.array(-big_angle / 2 + angles)
label_angle[label_angle < -np.pi / 2] += np.pi
# easier to read labels on the left side
# 繪製各個細菌的名字
p.text(xr, yr, df.bacteria, angle=label_angle,
text_font_size=
"9pt"
, text_align="center"
, text_baseline="middle"
)# 繪製圓形,其中數字分別為 x 軸與 y 軸標籤
p.circle([-40, -40], [-370, -390], color=list(gram_color.values()), radius=5)
# 繪製文字
p.text([-30, -30], [-370, -390], text=[
"Gram-"
+ gr for gr in gram_color.keys()],text_font_size=
"7pt"
, text_align="left"
, text_baseline="middle"
)# 繪製矩形,中間標籤部分。其中 -40,-40,-40 為三個矩形的 x 軸坐標。18,0,-18 為三個矩形的 y 軸坐標
p.rect([-40, -40, -40], [18, 0, -18], width=30, height=13,
color=list(drug_color.values()))
# 配置中間標籤文字、文字大小、文字對齊方式
p.text([-15, -15, -15], [18, 0, -18], text=list(drug_color),
text_font_size=
"9pt"
, text_align="left"
, text_baseline="middle"
)output_file(
"burtin.html"
, title="burtin.py example"
)show(p)
元素周期表
元素周期表,這個實現好牛逼啊,距離初三剛開始學化學已經很遙遠了,想當年我還是化學課代表呢!由於基本用不到化學了,這裡就不實現了。
Pyecharts
pyecharts 也是一個比較常用的數據可視化庫,用得也是比較多的了,是百度 echarts 庫的 python 支持。這裡也展示一下常用的圖表。文檔地址為(http://pyecharts.org/#/zh-cn/prepare?id=%E5%AE%89%E8%A3%85-pyecharts)
條形圖
from import "我的第一個圖表" "這裡是副標題" "服裝" "襯衫" "羊毛衫" "雪紡衫" "褲子" "高跟鞋" "襪子" 5 20 36 10 75 90 # bar.print_echarts_options() # 該行只為了列印配置項,方便調試時使用 # 生成本地 HTML 文件
bar = Bar(
bar.add(
bar.render()
散點圖
from 10 1 100 for in range 300
import random
data_1 = [(
data_2
11
, random.randint(1
,100
))for
iin
range
(300
)]polar = Polar(
"極坐標系-散點圖示例"
, width=1200
, height=600
)polar.
add
(""
, data_1, type="scatter"
)polar.
add
(""
, data_2, type="scatter"
)polar.render()
餅圖
import from import "A" "B" "C" "D" "E" "F" "餅圖示例" 1000 600 "" 0 100 for in 6 50 55 25 50 True "" 20 100 for in 6 0 45 25 50 "area" "" 0 100 for in 6 50 55 65 50 True "" 20 100 for in 6 0 45 65 50 "radius"
attr = [
pie = Pie(
pie.add(
attr,
[random.randint(
radius=[
center=[
is_random=
)
pie.add(
attr,
[random.randint(
radius=[
center=[
rosetype=
)
pie.add(
attr,
[random.randint(
radius=[
center=[
is_random=
)
pie.add(
attr,
[random.randint(
radius=[
center=[
rosetype=
)
pie.render()
詞雲
這個是我在前面的文章中用到的圖片實例,這裡就不 po 具體數據了。
# 詞條 # 權重 ""from pyecharts import WordCloud
name = ["Sam S Club"]
value = [10000]
wordcloud = WordCloud(width=1300, height=620)
wordcloud.add(
wordcloud.render()
樹圖
這個是我在前面的文章中用到的圖片實例,這裡就不 po 具體數據了。
from # 鍵值對數據結構 value 1212 # 數值 # 子節點 # 子節點數值 value 2323 # 子節點名 "description of this node" value 4545 "description of this node" value 5656 "description of this node" 1200 600 # 設置標題與寬高 add "深圳" "inside" 19
data = [
{
children: [
{
name:
children: [...],
},
{
name:
children: [
{
name:
children: [...]
},
...
]
}
]
},
...
]
treemap = TreeMap(title, width=
treemap.
treemap.render()
地圖
from pyecharts import Map
value = [155, 10, 66, 78, 33, 80, 190, 53, 49.6]
attr = [
"福建"
,"山東"
,"北京"
,"上海"
,"甘肅"
,"新疆"
,"河南"
,"廣西"
,"西藏"
]
map = Map(
"Map 結合 VisualMap 示例"
, width=1200, height=600)map.add(
""
,attr,
value,
maptype=
"china"
,is_visualmap=True,
visual_text_color=
"#000"
,)
map.render()
3D 散點圖
from random.randint(0, 100), for in range 80
import random
data = [
[
random.randint(0, 100),
random.randint(0, 100)
]
range_color
"#313695"
,"#4575b4"
,"#74add1"
,"#abd9e9"
,"#e0f3f8"
,"#ffffbf"
,"#fee090"
,"#fdae61"
,"#f46d43"
,"#d73027"
,"#a50026"
]scatter3D = Scatter3D(
"3D 散點圖示例"
, width=1200
, height=600
)# 配置寬高
scatter3D.
add
(""
, data, is_visualmap=True, visual_range_color=range_color)# 設置顏色等
scatter3D.render()
# 渲染
後記
大概介紹就是這樣了,三個庫的功能都挺強大的,bokeh 的中文資料會少一點,如果閱讀英文有點難度,還是建議使用 pyecharts 就好。總體也不是很難,按照文檔來修改數據都能夠直接上手使用。主要是多練習。
【本文作者】
Zone:一隻愛折騰的後端攻城獅,喜歡寫文分享。個人公眾號:zone7
推薦閱讀
(點擊標題可跳轉閱讀)
教你用 Python 做一個物體檢測系統
改善 Python 程序的 91 個建議
讓 Python 代碼更易維護的七種武器
覺得本文對你有幫助?請分享給更多人
關注「Python開發者」加星標,提升Python技能
![](https://pic.pimg.tw/zzuyanan/1488615166-1259157397.png)
![](https://pic.pimg.tw/zzuyanan/1482887990-2595557020.jpg)
※面向對象:和你一起把我活成「我們」
※一文讀懂 PySpark 數據框
TAG:Python開發者 |