pandas+matplotlibで3D棒グラフを作る
たとえば、こんな感じの表があったとするじゃないですか。
店 | うし | ぶた | とり |
---|---|---|---|
肉屋 | 580 | 280 | 300 |
スーパー | 420 | 260 | 320 |
これを、エクセルに入力して、挿入->3D-縦棒と選ぶと
こんな感じのかっこいい(?)グラフが作れるわけですが、これをpandas+matplotlibでやってみようというお話です。
結論から先に書くと
import pandas as pd import numpy as np import matplotlib.pyplot as plt from mpl_toolkits.mplot3d import Axes3D from matplotlib.font_manager import FontProperties df=pd.DataFrame({u"うし":[580, 420], u"とり":[280, 260], u"ぶた":[300, 320]}, index=(u"肉屋", u"スーパー")) ax=plt.figure().add_subplot(111, projection='3d') fp=FontProperties(fname=r'C:\WINDOWS\Fonts\msgothic.ttc', size=10) xpos,ypos=np.meshgrid(np.arange(len(df.index)), np.arange(len(df.columns))) xpos=xpos.flatten() ypos=ypos.flatten() zpos=np.zeros(len(xpos)) dx=np.full(len(xpos), 0.05) dy=np.full(len(ypos), 0.1) dz=df.as_matrix().flatten() ax.bar3d(xpos, ypos, zpos, dx, dy, dz) ax.set_xlabel(u"お店", fontproperties=fp) ax.set_ylabel(u"種類", fontproperties=fp) ax.set_zlabel(u"金額", fontproperties=fp) plt.xticks(np.arange(len(df.index)), df.index, fontproperties=fp) plt.yticks(np.arange(len(df.columns)), df.columns, fontproperties=fp) plt.axis([-0.5, len(df.index)-0.5, -0.5, len(df.columns)-0.5]) plt.savefig("hoge.png")
みたいなコードになります。
公式ページのexampleを見ると、
mplot3d example code: bars3d_demo.py — Matplotlib 1.4.3 documentation
ってのがありますが、こっちは普通の棒グラフを奥行方向に重ねて並べるもののようで、今回作ろうと思っていたのとはちょっと違います。
一見関係無さそうな名前ですが、
mplot3d example code: hist3d_demo.py — Matplotlib 1.4.3 documentation
のところで使っている、bar3d()が今回のグラフに必要な関数でした。
ところがこの関数、APIドキュメントがこんな調子でまったく意味不明です。
bar3d(x, y, z, dx, dy, dz, color=u'b', zsort=u'average', *args, **kwargs)
Generate a 3D bar, or multiple bars.
When generating multiple bars, x, y, z have to be arrays. dx, dy, dz can be arrays or scalars.
color can be:
A single color value, to color all bars the same color.
An array of colors of length N bars, to color each bar independently.
An array of colors of length 6, to color the faces of the bars similarly.
An array of colors of length 6 * N bars, to color each face independently.When coloring the faces of the boxes specifically, this is the order of the coloring:
-Z (bottom of box)
+Z (top of box)
-Y
+Y
-X
+XKeyword arguments are passed onto Poly3DCollection()
http://matplotlib.org/mpl_toolkits/mplot3d/api.html#mpl_toolkits.mplot3d.axes3d.Axes3D.bar3d
x, y, z have to be arraysとか言われても、何の値入れりゃえんじゃーと悩んでましたが、どうやら
- 各配列は全て同じ長さの1次元配列にする
- i番目の棒の左下隅の頂点座標をx, y, zのi番目の要素で指定
- i番目の棒の各軸方向の幅をdx, dy, dzのi番目の要素で指定
ということのようです。
ちなみに、この例ではx、yともに項目名なのであまり違和感は無いかもしれませんが、元々私がやってた時は2次元でパラメータを振った時の実験結果をプロットしようとしていたので、x, y, zに値を入れてからdx, dy, dzって何を入れるんだろうかと、かなりドツボにはまってました。*1
あとのところは、コードを見れば分かると思いますので、解説は省きますが
- set_?label
- ラベルの設定
- {x,y}ticks
- x/y座標の値の指定
- axis
- 座標軸の長さ指定
- savefig
- グラフを画像ファイルとして保存
です。
matplotlibの全般的な話は
matplotlib入門 - りんごがでている
に助けられました。ここ読まなかったら未だドキュメントの海で溺れてたと思いますorz
あと、フォント関連の設定については
Python - matplotlibで日本語 - Qiita
を参考にさせていただきました。
そういや、pandasろくに使って無いな・・・
windowsでのpython3のセットアップ
相変わらず仕事でpythonが絡むと「python2向けで」とか、下手すると「2.6で動作すること」とか言われますが、そろそろ自作のソフトくらいはpython3へ移行しようと思い立って、まずは環境を用意することにしました。
まずは、chocolateyからpython2/3をまとめてインストールします。
>choco install python python2 -y Chocolatey v0.9.9.7 Installing the following packages: python;python2 By installing you accept licenses for the packages. python v3.4.3.20150501 Get-BinRoot is going to be deprecated by v1. Many packages no longer require it since the folders no longer have versions on them. Downloading python 32 bit from 'https://www.python.org/ftp/python/3.4.3/python-3.4.3.msi' Installing python... python has been installed. The install of python was successful. python2 v2.7.10 Get-BinRoot is going to be deprecated by v1. Many packages no longer require it since the folders no longer have versions on them. Warning: Old installation path “C:\Python27” detected. This package will continue to install python2 there unless you uninstall python2 from there and remove the “C:\Python27” folder. If you decide to do that, reinstall this package with the -force parameter and it will install to the Chocolatey bin root. Installing python2... python2 has been installed. The install of python2 was successful. Chocolatey installed 2/2 package(s). 0 package(s) failed. See the log for details (C:\ProgramData\chocolatey\logs\chocolatey.log).
途中で別のwindowが開いたりしますが、インストール完了後に一旦コマンドプロンプトを開き直すと
> python --version Python 3.4.3 > C:\Python27\python.exe --version Python 2.7.10
といった形でpython2と3が無事に動くようになりました。
続いてvirtualenvのインストール
>C:\tools\python3\Scripts\pip install virtualenv You are using pip version 6.0.8, however version 7.1.2 is available. You should consider upgrading via the 'pip install --upgrade pip' command. Collecting virtualenv Downloading virtualenv-13.1.2-py2.py3-none-any.whl (1.7MB) 100% |################################| 1.7MB 63kB/s Installing collected packages: virtualenv Successfully installed virtualenv-13.1.2
では、さっそくvirtual envを使って、python2.7用の環境を作ってみましょう。
>python -m virtualenv --python=C:\Python27\python.exe Py27 Running virtualenv with interpreter C:\Python27\python.exe New python executable in Py27\Scripts\python.exe Installing setuptools, pip, wheel...done.
Py27フォルダに移動して、activateすると
>cd Py27 >Scripts\activate >python --version Python 2.7.10
となって、無事にpython2.7の環境ができました。
この状態からdeactivateすると素の環境に戻ります。
>deactivate >python --version Python 3.4.3
とりあえず、2.7と3.4用の開発環境を一式作っておこう。
chefをやめてchocolateyへ
単にパッケージをインストールするだけのこんな感じのレシピをいくつか書いた後でふと気づきました。
if platform_family?('windows') windows_package node['hoge']['display_name'] do source node['hoge']['url'] installer_type :custom action :install options "/quiet" end end
わざわざchefを使うまでの話でもないな・・・
というわけで、単純なインストール作業はchocolateyに
お任せすることにしました。
そうすると、今までchefでやってた作業で残るものは
- C:\WORKの作成
- 環境変数HOMEの設定
- gitで管理しているドットファイルの取得
- ssh鍵の作成
- フォントのインストール
- 環境変数PATHの設定(viとかのインストール先を追加したい)
- 自動起動の設定(主にautohotkey)
といったところです。
このうち、1, 2, 3, 6, 7についてはpowershellのスクリプトに移行しました。
4,5は大した手間でもないので、手作業でやってます。*1
私が考えていたchefの利点というのは以下の3つでした。
- 冪等性
- platform independent
- DSL
ところが、1のケースで考えると、そもそも既存のディレクトリが存在したら、ディレクトリは生成できるわけがないので、どんな手段を使うにしても冪等性を考える必要はないわけです。*2
同じように、3のケースであればgitコマンド自体が冪等性を保証してくれますし、ソフトのインストールについてもインストール済みであればwindowsのインストーラが大抵は勝手に判定してくれます。
環境変数の設定はbashのexportでもsetxコマンドでも考慮してくれないので、PATHに同じディレクトリが複数回設定されるような状況が容易に起こるわけですが、この程度のことのためにchefを導入するのは、役不足でしょう。
platform依存性という観点では、そもそも設定している内容がwindows環境だから設定しないといけないという性質のものばかりなので、実際のところ、これまでの運用ではあまり活かせてませんでした。
vagrantやvirtualboxみたいな、どんなOSでも入れたいソフトもあるので、こういったもののインストールはお任せしたいところなんですが、現状のchefではaptやyumやdmgやwindowsのような、各プラットフォームに対応するためのcookbookも準備する必要があって、少々煩わしいです。*3
あと、pythonとかnode.jsのような、重要なソフトのコミュニティcookbookがwindowsに対応していなくて、結局自分でwindows専用のcookbookを
書く羽目になるのも悲しいところです。
最後のDSLというのは、スクリプトで書き直していると重要性を痛感できるんですが、これまた環境変数の件と同じく、これだけのためにchefを導入するもんでもないなぁと感じてます。
というわけで、ほぼすべての自作cookbookは闇に葬られて、いくつかのpowershellスクリプトに生まれ変わりました。
windowsの"PROGRAMFILES"環境変数
32bit windowsでは、プログラムのインストール先はたいてい"C:Program Files"ですが、64bit windowsでは、64bitプログラムは"C:Program Files"に、32bitプログラムは"C:Program Files(x86)"に分けてインストールするのがお約束になっています。
この"Program Files"ディレクトリを参照する環境変数として%PROGRAMFILES%というのがあるんですが、この環境変数は呼び出し元プログラムが32bitか64bitかによって変わるようです。
C:\WORK>\Windows\SysWOW64\cmd.exe Microsoft Windows [Version 6.1.7601] Copyright (c) 2009 Microsoft Corporation. All rights reserved. C:\WORK>echo %PROGRAMFILES% C:\Program Files (x86) C:\WORK>exit C:\WORK>\Windows\System32\cmd.exe Microsoft Windows [Version 6.1.7601] Copyright (c) 2009 Microsoft Corporation. All rights reserved. C:\WORK>echo %PROGRAMFILES% C:\Program Files
一瞬逆に思えるけど、System32の下にあるのが64bit版で、SysWOW64の下にあるのが、32bit版のcmd.exeです。
インストーラ無しで配布されているプログラムをインストールする(chefの)recipeで、インストール先として
"#{ENV['PROGRAMFILES']}\\hoge"
みたいなのを指定してたら、git-bashから入れるとProgram Files(x86)に入るし、コマンドプロンプトから入れるとProgram Filesに入るし大混乱になりました・・・orz
一応、こんな感じで回避してますが、そもそもインストール先を選択する時に%PROGRAMFILES%を使うのは不適切だってことですね。
if kernel['machine'] =~ /x86_64/ default['install_to'] = "#{ENV['PROGRAMW6432']}" else default['install_to'] = "#{ENV['PROGRAMFILES']}" end
cmakeでC++ルーチンを呼び出すFortranプログラムをビルドする
自作のライブラリ(C++で作成、C、Fortranのインタフェースあり)をFortranのプログラムから呼び出すサンプルコードを書いてたんですが、CmakeList.txtの作成ではまったので、メモ
cmake fortran c++ mixedlink あたりでぐぐると、
SET_TARGET_PROPERTIESで、LINKER_LANGUAGE をCXXに設定するべし
という解決方法が定番のようです。実際にg++/gfortranの環境であればこれで問題無いんですが、intel コンパイラの場合は、この方法ではリンク時にエラーになります。
Compiling and Linking Intel® Fortran/C Programs
によると、リンク時に"-cxxlib"を渡せと書いてますが、これもうまく動作しなかったので、当面の回避策として、こんな形にしてみました。
project(hoge CXX C Fortran)
.
.
.
add_executable(huga huga.f90)
target_link_libraries(huga my_cxx_lib ${CMAKE_CXX_IMPLICIT_LINK_LIBRARIES})
要は、CXXコンパイラが暗黙的にリンクするライブラリを強制的にtarget_link_librariesで追加してるだけです。
これでPGIコンパイラとかでも動いてくれたらいいなぁ
chef -zeroでwindows用開発環境を構築(その4)
運用を始めてから気付いたことをバラバラとメモっときます。
gitでエラーになる
gitのレシピを実行すると、こんなエラーが発生する時があります。
FATAL: Errno::EIO: git[C:\WORK\unix_home] (update_home_dir::default line 10) had an error: Errno::EIO: Input/output error - CreateProcessW
ここにissueとして出てますが、gitじゃなくてgit.exeを呼ばないと発生するエラーだそうです。
git resource Errno::EIO on windows · Issue #1622 · chef/chef · GitHub
そのうち解決されると思いますが、とりあえずのワークアラウンドとしてこんな感じに修正しておきました。
if platform_family?('windows') git_command="git.exe" else git_command="git" end #clone remote repo to $HOME if not exist if ! ::File.directory?("#{ENV['HOME']}/.git") execute "git init" do command "#{git_command} init" cwd "#{ENV['HOME']}" end execute "git remote add" do command "#{git_command} remote add origin #{node['update_home_directory']['repo']}" cwd "#{ENV['HOME']}" end end execute "git pull" do command "#{git_command} pull origin master" cwd "#{ENV['HOME']}" end execute "git submodule" do command "#{git_command} submodule update --init --recursive" cwd "#{ENV['HOME']}" end
cloneせずに、わざわざinitしてからpullしてますが、これはこのエラーとは無関係で、gitが実行される前に%HOME%\.chefディレクトリが作られてしまってgit cloneに失敗することへの対策です。
windows_packageの羃等性
githubのページに書かれているように、windows_packageに渡す名前は[コントロールパネル]->[プログラムと機能]のリストに表示されている名前と正確に一致させていないと、インストール済かどうかの判定に失敗します。
opscode-cookbooks/windows · GitHub
でもって、この名前はプログラムによってバージョン名を含むものや含まないものが混在しているので、もしバージョン番号が入っていないソフトだったら、アップデートするのが難しくなるので違う名前にしておきましょう。(うちの環境だとAmazon KindleとかcourvusSKKとかがバージョン番号が無いです)
ログオン時に実行させる
スタートアップに追加するのは、専用のリソースが用意されていて、次のようなコードで登録できます。
windows_auto_run "autohotkey" do program node['autohotkey']['program_name'] not_if {Registry.value_exists?(AUTO_RUN_KEY, "autohotkey")} action :create end
ショートカットの追加
ショートカットも専用のリソースがあって、こんな感じで追加できます。
windows_shortcut "#{ENV['USERPROFILE']}\\Desktop\\gvim.lnk" do target exe_path description "gvim" action :create end
本当はスタートメニューとかタスクバーに登録したいんですが、こっちのやり方は分からず・・・
ファイルの関連付け変更
ファイルの関連付けは、コマンドラインからassocやftypeコマンドを使うのが正しいやり方だと思いますが、面倒なのでレジストリを直接いじります。しかし、ぐぐってみると昔のkeyも有効なようで
"HKEY_CURRENT_USER\\Software\\Classes\\.#{ext}\\shell\\open\\command"
に登録するパターンと
"HKEY_CURRENT_USER\\Software\\Classes\\#{ext}_auto_file\\shell\\open\\command"
に登録するパターンのどちらでも良いようです。(#{ext}は拡張子)
うちの環境でテストした限りでは、
という問題があるので、後者のkeyを使っています。
具体的にはgvimのレシピの中でこんな感じにしてます。
%w{rb py js txt log c C cpp h f F f90 F90}.each do |ext| registry_key "set file type assocication by auto_file #{ext}" do key "HKCU\\Software\\Classes\\#{ext}_auto_file\\shell\\open\\command" values [{ :name => "", :type => :string, :data => "#{exe_path} %1" }] recursive true end end
chef-zeroでwindows用開発環境を構築(その3)
再び続けてChef-zero on windowsの話です。
前回までで、まだ足りないソフトがあるものの、windows8.1用のchef-repoを作成してOneDriveに放り込み、chefによる環境設定の運用を開始することができました。
今回は、OndeDrive経由で別のwindowsマシンにも同じ環境を作ってみましょう。
ちなみに、新しいマシンはwindows7 pro(64bit)です。
下準備
msysgitとchef-clientをインストールします。内容は前々回と同じなので、詳細は省略
http://hpcmemo.hatenablog.com/entry/2015/03/19/125319
ノードの作成
chef-repoへ移動して以下のコマンドを実行します。
>chef-client -z [2015-03-23T12:44:21+09:00] WARN: No config file found or specified on command line, using command line options. Starting Chef Client, version 12.0.3 [2015-03-23T12:45:04+09:00] WARN: chef-client doesn't have administrator privileges on node new_pc. This might cause unexpected resource failures. resolving cookbooks for run list: [] Synchronizing Cookbooks: Compiling Cookbooks... [2015-03-23T12:45:04+09:00] WARN: Node new_pc has an empty run list. Converging 0 resources Running handlers: Running handlers complete Chef Client finished, 0/0 resources updated in 43.526 seconds
本当は、新規ノードを作成するには
> knife node create new_pc -z
で良いはずなんですが、何回やっても環境変数EDITORが設定されていないと言われて実行できなかったので・・・
run_listの追加とレシピの適用
1台目のマシンと同じですが、Admin権限をもったコマンドプロンプトで以下のコマンドを実行します。
> knife node run_list add new_pc firefox windows_initial_settings windows -z WARNING: No knife configuration file found new_pc: run_list: recipe[firefox] recipe[windows_initial_settings] recipe[windows] > chef-client -z [2015-03-25T13:51:33+09:00] WARN: No config file found or specified on command line, using command line options. Starting Chef Client, version 12.0.3 resolving cookbooks for run list: ["firefox", "windows_initial_settings", "windows"] Synchronizing Cookbooks: - firefox - windows_initial_settings - windows - chef_handler Compiling Cookbooks... Recipe: windows::default * chef_gem[win32-api] action install (up to date) * chef_gem[win32-service] action install (up to date) * chef_gem[windows-api] action install (up to date) * chef_gem[windows-pr] action install (up to date) * chef_gem[win32-dir] action install (up to date) * chef_gem[win32-event] action install (up to date) * chef_gem[win32-mutex] action install (up to date) Converging 13 resources Recipe: firefox::default * windows_package[Mozilla Firefox 36.0.4 en-US] action install Recipe: <Dynamically Defined Resource> * remote_file[C:\WORK\unix_home\.chef\local-mode-cache\cache/Firefox Setup 36.0.4.exe] action create - update content in file C:\WORK\unix_home\.chef\local-mode-cache\cache/Firefox Setup 36.0.4.exe from e3b0c4 to 15f75d (file sizes exceed 10000000 bytes, diff output suppressed) Recipe: windows_initial_settings::default * directory[C:WORK] action create (up to date) * git[C:\WORK\unix_home] action syncPassword for 'https://n_so5@bitbucket.org': (up to date) * env[HOME] action create (up to date) * directory[C:\WORK\unix_home\.ssh] action create (up to date) * execute[ssh-keygen] action run (skipped due to not_if) Recipe: windows::default * chef_gem[win32-api] action install (up to date) * chef_gem[win32-service] action install (up to date) * chef_gem[windows-api] action install (up to date) * chef_gem[windows-pr] action install (up to date) * chef_gem[win32-dir] action install (up to date) * chef_gem[win32-event] action install (up to date) * chef_gem[win32-mutex] action install (up to date) Running handlers: Running handlers complete Chef Client finished, 2/20 resources updated in 155.402539 seconds
既に環境変数が設定済だったり、鍵が生成済だったりするので、イロイロ飛ばされてますが、あっさりと適用できました。
あとは、インストールする各アプリのレシピを育てていけば、いつでもお手軽に新しいwindowsマシンのセットアップができますね。