Plotly是一個用於做分析和視覺化的線上平台, 被稱為有史以來最牛逼的視覺化神器. 其功能強大到不僅與多個主流繪圖軟體的對接, 而且還可以像Excel那樣實現互動式製圖, 而且圖表種類齊全, 可以實現線上分享以及開源。
plotly-express 以 html 顯示圖例,需使用瀏覽器顯圖。
Plotly的功能
關於Plotly的功能介紹, 有如下
1. 基本圖表:20種
2. 統計和海運方式圖:12種
3. 科學圖表:21種
4. 財務圖表:2種
5. 地圖:8種
6. 3D圖表:19種
7. 擬合工具:3種
8. 流動圖表:4種
…………
Plotly Express
plotly雖然功能強大, 卻一直沒有得到廣泛應用, 最主要的原因就是plotly的設置過於繁瑣. 因此, plotly 再度的推出簡化介面:Plotly Express, 簡稱 px. px採用ROR等新一代 “約定優先” 程式設計模式, 內置了大量實用、現代的繪圖範本, 使用者只需調用簡單的api函數, 即可生成漂亮的互動畫面.
px 是 Plotly.py 的高度封裝, 它為複雜的圖表提供了一個簡單的語法. 且px與 Plotly 完全相容. 而px內置了的圖表組合, 已涵蓋了90%常用的繪圖需要。
px 所吃的資料,亦是 DataFrame。DataFrame雖也可以繪制圖表,只是它調用 Matplotlib 進行圖表繪制。而 px 則採用網頁格式顯示圖表。
安裝套件
本例需安裝套件
pip install plotly plotly-express
常用指令
px.scatter() : 點散圖 px.choropleth() : 地理數據 px.bar() : 長條圖 px.line() : 折線圖 px.box() : 箱型圖 px.violin() : 小提琴圖 px.scatter_3d() : 3D點散圖 px.add_trace(go.Scatter()) : 軌跡圖 + 點散圖
gapminder資料
px也提供了一些內建的資料, 使用px.data.gapminder()即可取得DataFrame的格式, 底下列印一部份的資料. 由結果可知, 這份資料是統計每一年每個國家的平均人民壽命, 人口數, GPD所得
import plotly_express as px import pandas as pd pd.set_option('display.max_rows', None) pd.set_option('display.max_columns', None) pd.set_option('display.width', None) pd.set_option('display.max_colwidth', None) df = px.data.gapminder().query('year == 2007') print(df) 結果 : country continent year lifeExp pop gdpPercap iso_alpha iso_num 11 Afghanistan Asia 2007 43.828 31889923 974.580338 AFG 4 23 Albania Europe 2007 76.423 3600523 5937.029526 ALB 8 35 Algeria Africa 2007 72.301 33333216 6223.367465 DZA 12 47 Angola Africa 2007 42.731 12420476 4797.231267 AGO 24 59 Argentina Americas 2007 75.320 40301927 12779.379640 ARG 32 71 Australia Oceania 2007 81.235 20434176 34435.367440 AUS 36 83 Austria Europe 2007 79.829 8199783 36126.492700 AUT 40 95 Bahrain Asia 2007 75.635 708573 29796.048340 BHR 48
簡易圖表
底下的代碼, 說明如何在Pycharm中顯示plotly_express的使用方式. 早期如果舊版plotly_express,需使用plotly.offline.plot(px.scatter())才可將chart顯示在Chrome裏。但新版的plotly_express,則使用show()即可由Chrome顯示圖型。
代碼中, px.data.gapminder()取得內建的資料庫, 圖表為2007年中, 各個國家的GDP所得與平圴壽命比較圖, 不同的洲別使用不同的顏色標示出來
#!/usr/bin/python3 import plotly_express as px import plotly file='plotly_simple.html' df = px.data.gapminder().query('year == 2007') chart=px.scatter(df, x='gdpPercap', y='lifeExp', color='continent')
chart.show() plotly.offline.plot(chart,filename=file, auto_open=False) print('<iframe src="/python/plotly/{0}" width="800" height="650"></iframe>'.format(file))
上述每個點代表一個國家, 可以依每個國家的人口數加大圓點的大小, size=’pop’ size_max=60. 另外滑鼠移到圓點時顯示國家別, 只要加入hover_name=’country’即可, 如下代碼
#!/usr/bin/python3 import plotly_express as px import plotly file='plotly_scatter1.html' df = px.data.gapminder().query('year == 2007') chart=px.scatter(df, x='gdpPercap', y='lifeExp', color='continent',
size='pop', size_max=60, hover_name='country')
chart.show()
分類
一不作, 二不休, 繼續來搞個更複雜的, 依照各洲進行分類, 完整代碼如下
#!/usr/bin/python3 import plotly_express as px import plotly file='plotly_scatter2.html' df = px.data.gapminder().query('year == 2007') chart=px.scatter(df, x='gdpPercap', y='lifeExp', color='continent',
size='pop', size_max=60, hover_name='country',
facet_col='continent')
chart.show()
動畫
將每一年的GPD與壽命製作成動畫, 這是相當強悍的功能. 但只需指定年份為每個影格的變數 animation_frame=’year’, range_x=[100,100000], range_y=[25,100].
另外加上log_x=True, 是指要將X軸的範圍, 以10的倍數增長, 如此就可以將10~10k之間的長度加大, 而10k~100k之間的長度縮小. 因為大部份的值都是落在10-10k之間
#!/usr/bin/python3 import plotly_express as px import plotly file='plotly_animation.html' df = px.data.gapminder() chart=px.scatter(df, x='gdpPercap', y='lifeExp', color='continent',
size='pop', size_max=60, hover_name='country',
animation_frame='year', animation_group='country',
range_x=[100,100000], range_y=[25,90], log_x=True)
chart.show()
地理數據
以上的數據, 也可以使用世界地圖及顏色來標示(真的是太強悍了). 首先必需使 px.choropleth()來繪製圖型. 重要的參數為 dataframe, locations必需為AFG等國際標準碼, color_continuous_scale顏色標示順序範本.
其他的就屬animation_frame(動畫的依據)及projection(投影方式), 這二個是選項值
#!/usr/bin/python3 import plotly_express as px import plotly file='plotly_map.html' df = px.data.gapminder() chart=px.choropleth(df, locations='iso_alpha', color_continuous_scale=
px.colors.sequential.Plasma,
color='lifeExp', animation_frame='year',
projection='natural earth')
chart.show()
長條圖
底下使用minder[minder[‘iso_alpha’]==’TWN’] 取得 台灣的DataFrame資料後, 再使用 px.bar()將每年的人口數印出. 參數只有data, x, y三個
#!/usr/bin/python3 import plotly_express as px import plotly df = px.data.gapminder() df=df[df['iso_alpha']=='TWN'] chart=px.bar(df, x='year', y='pop', title='台灣歷年人口數量')
chart.show()
股市 px 版
本例需安裝套件
pip install yfinance plotly-express
繪製折線圖使用 px.line,裏面吃的格式為 Pandas 的 DataFrame,再由 y=[] 指定要繪製的欄位。本例使用 yfinance 爬取聯發科股價再繪製走勢圖及迴歸線,完整碼如下。
from datetime import datetime
import yfinance as yf
import plotly_express as px
import numpy as np
current=datetime.now()
df=yf.download("2454.TW", '1970-01-01', auto_adjust=True)
#新增日期欄
df.insert(0,'Date',df.index)
#新增迴歸線
x=range(df.shape[0])
f=np.poly1d(np.polyfit(x, df['Close'], 10))
df.insert(0,'Reg', f(x))
#畫線
fig=px.line(
df, x='Date', y=['Close', 'Reg'],
color_discrete_sequence=['blue', 'orange'],
title="聯發科"
)
fig.show()
‘
黃金 px 版
底下由資料庫讀取黃金儲摺買進及賣出資料,然後繪製走勢圖。
import plotly_express as px import plotly import mysql.connector as mysql import pandas as pd conn=mysql.connect(host="ip",user="帳號", password="密碼", database="資料庫") cmd="select * from 台銀黃金 order by 日期" cursor=conn.cursor() cursor.execute(cmd) rs=cursor.fetchall() columns=['id','日期', '買進', '賣出'] df=pd.DataFrame(data=rs, columns=columns) fig=px.line( df, x='日期', y=['買進','賣出'], color_discrete_sequence=['blue','red'], title='黃金存摺' ) fig.show()
箱型圖
箱型圖可取得每一種狀態的最低值, 最高值, 及平圴值. 那麼, 那一個欄位有這種特性呢, 比如亞洲每一個國家的人民壽命.
試想一件事, 若想要使用箱型圖列出台灣每一年的人民壽命, 那結果如何 ?? 當然是每一年只有一條線, 因為每年只有一筆資料.
#!/usr/bin/python3 import plotly_express as px import plotly file='plotly_box.html' df = px.data.gapminder() df=df[df['continent']=='Asia'] chart=px.box(df, x='year', y='lifeExp', title='亞洲人歷年壽命')
chart.show()
小提琴圖
violin可以說是箱型圖的改良版, 可以顯示不同國家不同的值
#!/usr/bin/python3 import plotly_express as px import plotly file='plotly_violin.html' df = px.data.gapminder() df=df[df['continent']=='Asia'] chart=px.violin(df, x='year', y='lifeExp', title='亞洲人歷年壽命')
chart.show()
px.scatter_3d
plotly-express目前有scatter_3d及 line_3d。至於長條圖等圖表,則沒有3D的效果。底下可繪製出圓柱彈簧的效果。
import plotly_express as px import plotly import pandas as pd import numpy as np pd.set_option('display.max_columns', None) pd.set_option('display.max_rows', None) pd.set_option('display.width', None) pd.set_option('display.max_colwidth', None) x=[] y=[] z=[] r=100 for i in range(360*10): x.append(r*np.cos(np.pi*i/180)) y.append(r * np.sin(np.pi * i / 180)) z.append(i/100) df=pd.DataFrame(data={"x":x, "y":y, "z":z}) fig=px.scatter_3d(df, x="x", y="y", z="z")
fig.show()