オタク日記
(Mac と Linux, 2017Q4)

目次

2017-12-28 (Thu): Matplotlib, お前もかっ! (その 2)

古い日記:
2017Q3   2017Q2   2017Q1  
2016Q4   2016Q3   2016Q2   2016Q1  
2015Q4   2015Q3   2015Q2   2015Q1  
2014Q4   2014Q3   2014Q2   2014Q1  
2013Q4   2013Q3   2013Q2   2013Q1  
2012 年   2011 年   2010 年   2009 年   2008 年   2007 年  
2006 年   2005 年   2004 年   2003 年   2002 年   2001 年


2017-12-28 (Thu): Matplotlib, お前もかっ! (その 2)

Matplotlib-2 (mpl-2) で「あるべきプロット」を目指す

「Matplotlib, お前もかっ!」の記事を書いてから、もう 1 年にもなるのか……。 その時は「しばらくは、1.5.3 で凌ごう」なんて殊勝な決意をしていたようだが、 私がこのような件で一年も放置(我慢)できる筈がない。 つい、色々ごちゃごちゃと「時間の無駄」をやってました。

さて、その時の「かくあるべし」を再掲すると、

  1. プロットする範囲は実線で囲む。
  2. tick はその実線の枠の内側に、tick value (目盛値) は tick に対応する箇所に書く。
  3. X/Y 軸の両端にも tick value をつける。
  4. Y 軸のラベルは、横書を 90 度回転したもの。
  5. 理論値、計算値は太い実線で、
  6. データポイントは、(中抜きの)○ で、
  7. データポイントに線を追加する場合は、 (データポイントを結ぶ「折れ線」ではなく)「スムージングした曲線」を示す。
  8. 複数のデータをプロットする場合は、色分けではなく、 マーカーの形や、line style を変える事で識別する。

この内、8. は既に無意味な制限になっているようなので、無視するとしても、 そこで例示したグラフは、上の 6. に違反している。(つまり、「中抜き」の circle になっていない。)Matplotlib-1.x (以下、mpl-1) ではすぐにはやり方が思い出せなかった……

Matplotlib-2.x (以下 mpl-2) でこれを実現するのは然程難しくはなく、些 かの cut & try で次にようなプロットを得た。

Reference Plot with MPL2
MPL-2 で実現する「あるべき Plot」
(click して拡大)

Mpl-2 でのディフォルトにする

ただこれをディフォルトにする、 すなわち最少のパラメータ変更でこのようなプロットを得られるようにする、 のは少々面倒だった。

Mpl-2 のインストールは様々な方法で可能であるが、ここではPyVenv (% python36 -m venv pve36 で作った環境) だと仮定する。 この場合、pip で matplotlib をインストールすると、

(pve36) fukuda@hawk:~/pve36% find . -name matplotlibrc
./lib/python3.6/site-packages/matplotlib/mpl-data/matplotlibrc
のように matplotlibrc が置かれるので、 これを、home directory (~/pve36/) にコピー・編集して
(pve36) fukuda@hawk:~/pve36% diff matplotlibrc.orig matplotlibrc 
#1)
336,340c336,338
< #axes.autolimit_mode : data # How to scale axes limits to the data.
ber
< #axes.xmargin        : .05  # x margin.  See `axes.Axes.margins`
< #axes.ymargin        : .05  # y margin See `axes.Axes.margins`
---
> axes.autolimit_mode : round_numbers
> axes.xmargin        : 0.0  # x margin.  See `axes.Axes.margins`
> axes.ymargin        : 0.0  # y margin See `axes.Axes.margins`
    
#2)
364c362
< #xtick.top            : False   # draw ticks on the top side
---
> xtick.top            : True   # draw ticks on the top side
374c372
< #xtick.direction      : out    # direction: in, out, or inout
---
> xtick.direction      : in    # direction: in, out, or inout
382c380
< #ytick.right          : False  # draw ticks on the right side
---
> ytick.right          : True  # draw ticks on the right side
391c389
< #ytick.direction      : out    # direction: in, out, or inout
---
> ytick.direction      : in    # direction: in, out, or inout
<
ここに、
  1. #1) axes.autolimit_mode と axes.{x|y}margin の変更によって、tick とそれに対応する label が表示範囲の端につくようになる。
  2. #2) これらの変更によって、表示範囲の四周に「内向き」の tick がつくようになる。

こうしておくと、次のような Python command で、上記のプロットが得られる。

(pve36) fukuda@hawk:~/pve36% ipython
Python 3.6.4 (default, Dec 21 2017, 20:32:44) 
Type 'copyright', 'credits' or 'license' for more information
IPython 6.2.1 -- An enhanced Interactive Python. Type '?' for help.

In [1]: import numpy as np

In [2]: import matplotlib.pyplot as plt

In [3]: x = np.arange(-10, 10, 0.01)

In [4]: y = np.cos(x)*np.exp(-x*x/10) + 0.5

In [5]: x1 = np.arange(-10, 10, 0.7)

In [6]: y1 = np.random.normal(np.cos(x1)*np.exp(-x1*x1/10) + 0.5, 0.02)

In [7]: plt.plot(x, y, x1, y1, 'o', mfc="white")
Out[7]: 
[<matplotlib.lines.Line2D at 0x1090513c8>,
 <matplotlib.lines.Line2D at 0x109051518>]

In [8]: plt.xlabel("Radial Position (m)")
Out[8]: Text(0.5,0,'Radial Position (m)')

In [9]: plt.ylabel("Magnetic Field (A/m)")
Out[9]: Text(0,0.5,'Magnetic Field (A/m)')

In [10]: plt.show() 

上記 [1]〜[6] は「データの作成」だし、[8], [9] は言わばつけ足しで、 データを確認する段階では普通はこんな事はやらないので、 ここでの肝は、[7] の記述。これをできるだけ簡略化したい、というのが目標で、 理想は plt.plot(x, y, x1, y1, 'o') だけで済ます事だが、残念ながら、 mfc="white" を省略するために必要な matplotlib の対応パラメータ (例えば markers.fillcolor?) を見つけられなかった。

少々不本意ではあるが、mfc="white" を省略しても、まあ我慢できるプロットができるので、 このあたりで手を打つ事にする。


118/1,729,017 Valid CSS! Valid HTML 5.0
Taka Fukuda
Last modified: 2018-02-14 (Wed) 14:50:49 JST