Matplotlib 軸的格式


在〈NumPy 載入文字檔〉載入的資料,總該畫個圖表之類,比較容易理解吧!使用 Matplotlib 的話蠻方便的,不過寫了這些程式碼後:

import numpy as np
import matplotlib.pyplot as plt

hist = np.fromregex('MI_5MINS_HIST.csv', 
                    r'"(.+)","([\d,.]+)","(.+)","(.+)","(.+)",', 
                    encoding = 'Big5', dtype = np.str)

date = hist[:,0]
opening = hist[:,1]

plt.title('一月開盤指數')
plt.xlabel('日期')
plt.ylabel('指數')
plt.plot(date, opening)
plt.show()

執行後的圖表卻是:

Matplotlib 軸的格式

嗯…中文沒出來,日期擠在一起,線圖也沒反映指數…XD

想要顯示中文的話,必須指定字型資訊,我是直接透過 pip install matplotlib 安裝 Matplotlib,在這個情況下,最簡單的設定方式是,在執行指令的資料夾中新增一個 matplotlibrc 檔案,撰寫以下的資訊:

font.family : Microsoft JhengHei

在 Windows 10 中有微軟正黑體,字型家族名稱是 Microsoft JhengHei,這樣就可以顯示中文了。

至於日期的部份,不想要它們擠在一起,最簡單的方式是取得目前的圖表物件,執行它的 autofmt_xdate 方法,這會將日期以 45 度斜放:

Matplotlib 軸的格式

雖然日期是看得出來了,不過還是太密集了一些,若想調整間距,可以使用 plt.gca() 取得軸物件,然後指定軸設定相關資訊,例如:

import matplotlib.dates as dates

...

axes = plt.gca()
axes.xaxis.set_major_locator(dates.DayLocator(interval=5))

這樣就會五個數據顯示一次文字:

Matplotlib 軸的格式

可以指定的單位有:

  • SecondLocator
  • MinuteLocator
  • HourLocator
  • DayLocator
  • WeekdayLocator
  • MonthLocator
  • YearLocator

如果你的日期時間資訊,已經剖析為 datetime 物件,可以透過 mdates.DateFormatter 來剖析並指定給 set_major_formatter,例如:

axes.xaxis.set_major_formatter(dates.DateFormatter('%Y-%m-%d'))

至於圖表不會隨著資料變化的問題,是因為指定了字串,像 '14,720',你必須剖析為浮點數,不過你不能直接使用 float 來剖析,它不認得那個千分位的逗號。

當然,自己將那個逗號取代為空白字元,就可以用 float 來剖析,不過更好的方式呢?可以透過 Python 內建的 locale 模組,設定區域化的數值格式,之後使用 locale.atof 來剖析,例如:

import locale

...

locale.setlocale(locale.LC_NUMERIC, 'zh_TW.UTF-8')
atof = np.frompyfunc(locale.atof, 1, 1)

... 

opening = atof(hist[:,1]) 

這麼一來 opening 就都是浮點數了,這時交給 Matplotlib 繪圖,就會顯示正確的圖表了,然而,y 軸的部份顯示指數時,沒有千分位逗號,類似地,可以對 y 軸格式化,或設定間距:

...

axes.yaxis.set_major_formatter(ticker.StrMethodFormatter('{x:,.0f}'))
axes.yaxis.set_major_locator(ticker.MultipleLocator(500))

將以上整理一下,重新撰寫的程式如下:

import numpy as np
import matplotlib.pyplot as plt
import matplotlib.dates as dates
import matplotlib.ticker as ticker
import locale

locale.setlocale(locale.LC_NUMERIC, 'zh_TW.UTF-8')

atof = np.frompyfunc(locale.atof, 1, 1)

hist = np.fromregex('MI_5MINS_HIST.csv', 
                    r'"(.+)","([\d,.]+)","(.+)","(.+)","(.+)",', 
                    encoding = 'Big5', dtype = np.str)

date = hist[:,0]
opening = atof(hist[:,1])

plt.title('一月開盤指數')
plt.xlabel('日期')
plt.ylabel('指數')

axes = plt.gca()
axes.xaxis.set_major_locator(dates.DayLocator(interval=5))
axes.yaxis.set_major_formatter(ticker.StrMethodFormatter('{x:,.0f}'))
axes.yaxis.set_major_locator(ticker.MultipleLocator(500))

plt.gcf().autofmt_xdate()
plt.plot(date, opening)
plt.show()

顯示出來的圖表就是:

Matplotlib 軸的格式