5.4 圖表繪製 : 作圖模板的擴展 : 添加副軸及細分類

5.4 圖表繪製 : 作圖模板的擴展 : 添加副軸及細分類

來自專欄報告自動化生成

# -*- coding:utf-8 -*-import numpy as npimport pandas as pdfrom IPython.display import Image as ShowImageimport matplotlib.pyplot as pltimport matplotlib as mplimport matplotlib.font_manager as mfmimport matplotlib.gridspec as gridspecimport matplotlib.ticker as plticker

目標圖表形式

ShowImage(./source/twinx.png)

data = pd.read_csv(./source/data_4.csv, index_col=0)data.head()

繼承模板

觀察多線圖和上一章中柱形圖的差異,可以發現以下結構有不同:

  • 畫圖方式:由折線圖和柱狀圖組成
  • Tick顯示:顯示日期
  • Legend在上側
  • y軸的Major tick label左右側都有,而且還有y軸Label

所以在這些部分我們需要進行相關的自定義

首先我們定義雙軸的通用Image類

%run Images.pyclass ImageTwinx(Image): def __init__(self, title=None, labels=None, data=None, image_path=None, xticks_rotation=40, legend_name=[], y2=None, title_y=1.2, ylabel_show=True): self.ylabel_show = ylabel_show self.legend_name = legend_name self.marker_style = dict(color=self.default_colors[blue], linestyle=-) # 副軸所用數據 self.y2 = y2 super(ImageTwinx, self).__init__(title=title, labels=labels, data=data, image_path=image_path, xticks_rotation=xticks_rotation, title_y=title_y, legend_name=legend_name) def config_add(self): self.set_ylabel() # 此處使用Legend作為y軸的Label def set_ylabel(self): if self.ylabel_show: self.ax.set_ylabel(self.legend_name[0], fontproperties=self.ylable_font) self.ax2.set_ylabel(self.legend_name[1], fontproperties=self.ylable_font) # 添加副軸,要加入init函數中set_xticks之後,作為初始化的一部分 def add_ax(self): self.ax2 = self.ax.twinx() def plot(self): self.ax.plot(self.x, self.y, label=self.legend_name[0], **self.marker_style) self.ax2.bar(self.x, self.y2, 0.4, zorder=3, label=self.legend_name[1], color=self.default_colors[red]) def set_spines(self): for _ax in [self.ax, self.ax2]: _ax.margins(0) # 設置留白 _ax.spines[right].set_visible(False) _ax.spines[top].set_visible(False) _ax.spines[left].set_visible(False) def set_tick_marks(self): self.ax.tick_params(axis=both, which=both, bottom=False, top=False, labelbottom=True, left=False, right=False, labelleft=True) self.ax2.tick_params(axis=both, which=both, bottom=False, top=False, labelbottom=True, left=False, right=False) def add_legend(self): if not (self.legend_name is None): if len(self.legend_name) == 2: lines1, labels1 = self.ax.get_legend_handles_labels() lines2, labels2 = self.ax2.get_legend_handles_labels() self.ax.legend(lines1+lines2, labels1+labels2, loc=upper center, ncol=2, bbox_to_anchor=(0.5, 1.27), prop=self.legend_font, frameon=False)image = ImageTwinx(data=data[u平均價格($)], y2=data[u平均價格變動量($)], labels=data[u日期], title=uTop100商品每日平均價格, legend_name=[u平均價格($), u平均價格變動量($)], xticks_rotation=0 )image.init()image.fig有雙軸需要設置副軸grid

此時圖表大部分已經符合要求,但是X軸的ticks需要設置下顯示方式,對於labels需要間隔顯示

def set_xticks(self): plt.xticks(range(0,self.length,30), self.labels.loc[[0, 30, 60, 90, 120, 150, 180]], fontproperties=self.xticks_font, rotation=self.xticks_rotation )

然後我們需要把set_xticks方法加入ImageTwinx中,這裡有三種方式可供選擇:

  1. 繼承ImageTwinx類做一個新的子類,使用set_xticks方法
  2. 用新的set_xticks方法替換掉ImageTwinx類中的set_xticks方法,相當於對類直接改變
  3. 在實例化之後的ImageTwinx類中bound新的set_xticks方法,需要使用MethodType function in the types module,具體可以參考stackoverflow

class ImageFluctuation(ImageTwinx): def set_xticks(self): plt.xticks(range(0,self.length,30), self.labels.loc[[0, 30, 60, 90, 120, 150, 180]], fontproperties=self.xticks_font, rotation=self.xticks_rotation)image = ImageFluctuation(data=data[u平均價格($)], y2=data[u平均價格變動量($)], labels=data[u日期], title=uTop100商品每日平均價格, legend_name=[u平均價格($), u平均價格變動量($)], xticks_rotation=12 # 設置x軸ticks的傾斜角度為12度 )image.init()image.fig有雙軸需要設置副軸grid

手動設置Y軸取值範圍

# image.fig.savefig(./source/twinx.png, dpi=160, bbox_inches=tight)

作業

作為作業,可以自行構造一個雙軸Bar形圖


推薦閱讀:

Origin(Pro):Grouped Stacked Columns【視頻】
Origin(Pro):3D圖-投影、垂線、標籤
【 ? 〃 素 材 】可愛手繪圖兒童系列 -
彩鉛繪圖技法
Origin(Pro):3D圖--Error Bar

TAG:繪圖 | Matplotlib | 高效工作 |