matplotlibで3Dプロット

matplotlibの三次元プロットで複数axisを生成する方法がありましたので、コードを書いてみました。

import numpy as np
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D

N = 20

fig = plt.figure(figsize = (8, 6))

ax = fig.add_subplot(2, 2, 1, projection = '3d', azim = 0)
bx = fig.add_subplot(2, 2, 2, projection = '3d', azim = 30)
cx = fig.add_subplot(2, 2, 3, projection = '3d', azim = 120)
dx = fig.add_subplot(2, 2, 4, projection = '3d', azim = 210)

axes = [ax, bx, cx, dx]
colors = ['red', 'blue', 'green', 'orange']
markers = ['o', '^', 'x', 'D']

for axis, i in zip(axes, range(4)):
	np.random.seed(i)
	
	sample = np.random.uniform(0, 3, size = (N, 3))
	
	X = sample[:, 0]
	Y = sample[:, 1]
	Z = sample[:, 2]
	
	axis.scatter(X, Y, Z, color = colors[i], marker = markers[i], alpha = .5)
	
	axis.set_xlabel(r'X axis')
	axis.set_ylabel('Y axis')
	axis.set_zlabel('Z axis')
	
	axis.set_xlim(0, 3.5)
	axis.set_ylim(0, 3.5)
	axis.set_zlim(0, 3.5)
	
	axis.set_xticks(range(4))
	axis.set_yticks(range(4))
	axis.set_zticks(range(4))	
	
	axis.set_xticklabels(range(4))
	axis.set_yticklabels(range(4))
	axis.set_zticklabels(range(4))
	
	
	
	axis.grid(True)


fig.tight_layout()
plt.show()

こんな感じの図が得られると思います。

f:id:jinpei0908:20160822185853p:plain

三次元プロットが一つでいい場合は

ax = Axes3D(fig)

のように書いても大丈夫ですが、いくつか並べる必要があるときには上記のやり方でやったほうがいいと思います。

あと乱数生成の時に先にnp.random.seedと書くとその直後に生成される乱数は固定のものが出てきます。

import numpy as np

np.random.seed(0)

print(np.random.randn(6, 2))
print('\n')

print(np.random.randn(6, 2))
print('\n')
np.random.seed(0)

print(np.random.randn(6, 2))
print('\n')

とすると

[[ 1.76405235 0.40015721]
[ 0.97873798 2.2408932 ]
[ 1.86755799 -0.97727788]
[ 0.95008842 -0.15135721]
[-0.10321885 0.4105985 ]
[ 0.14404357 1.45427351]]


[[ 0.76103773 0.12167502]
[ 0.44386323 0.33367433]
[ 1.49407907 -0.20515826]
[ 0.3130677 -0.85409574]
[-2.55298982 0.6536186 ]
[ 0.8644362 -0.74216502]]


[[ 1.76405235 0.40015721]
[ 0.97873798 2.2408932 ]
[ 1.86755799 -0.97727788]
[ 0.95008842 -0.15135721]
[-0.10321885 0.4105985 ]
[ 0.14404357 1.45427351]]
となります。

参考は以下に

bicycle1885.hatenablog.com

http://d.hatena.ne.jp/sobasobasoba/touch/20131230/1388367688http://d.hatena.ne.jp/sobasobasoba/touch/20131230/1388367688d.hatena.ne.jp

久しぶりに書きます

タイトルのとおりですが久しぶりに書きます。

先日までテストがあったのであまりコードを書く時間もなく、ブログも書けませんでした。
機械学習とか春ぐらいに勉強していたc++について調べたりしてはいましたが…

pythonとかswiftとかと書いておきながら最近はあまりswiftはやってません。どうも今はswift2.0ぐらいらしいのですが、また新しいswift3.0がでて多少仕様が変わるとか。初心者の自分に影響が出るようなほど抜本的な仕様変更ではないと思いますが、あまり解説サイトなどもなくライブラリも豊富ではなさそうなので、swiftは置いといて、同じマルチパラダイムで前まで勉強していて下地のあるc++を勉強しなおしていました。

c/c++の動的配列は未だに理解していません。なんというかイメージがしにくいので、どう書いていいものかと悩みます。

とりあえず、c++pythonで単純パーセプトロンの勉強を目下していこうかと思ってます。

itertoolsについて

itertoolsというモジュールを使うことで、順列組み合わせを表現できるようです。

もっと高度なことができるようですが、自分の使い方だとそこまで使わないかな
という感じです。順列を使えるようになるとfor文のネストを減らすことができて見た目的にきれいに書けますね。

あとパッとは思いつきませんが組み合わせも割りと使う場面が多いかもしれません。

ということで、サンプルコードです。

import numpy as np
import itertools as its


#順列
a = np.arange(3)

for i, j in its.product(a, a):
    print(i, j)

#out
'''
0 0
0 1
0 2
1 0
1 1
1 2
2 0
2 1
2 2
'''

#組み合わせ
b = np.arange(5)

for i, j in its.combinations(b, 2):
    print(i, j)

#out
'''
0 1
0 2
0 3
0 4
1 2
1 3
1 4
2 3
2 4
3 4
'''

productの引数はイテレータを渡すらしいです。combinationsはイテレータと何個選ぶかを引数として渡します。

イテレータが何なのかについてははっきり言うとあまりわかっていないのですが、
まず使えるようになってから調べていこうと思います。

以下参考:
kk6.hateblo.jp

参考にさせていただいたブログには詳説が書かれているので、また勉強するときに参考にさせていただこうと思います。

実際これをpaizaの問題を解くときに導入してみたのですが、for文の二重ネストのときは最大1秒程度で
itertoolsを使った時は最大5秒もかかっていました。入力が同じかどうかが確認できないのでなんとも言えないですが、itertoolsを使った時のほうが時間が異常にかかっていました。
単純にpaizaの実行環境の問題なのか、はたまたitertoolsの使い方の問題なのかわかりませんが、使いどころは割りと見極めたほうがいいのかもしれません。

プログラミング歴

プログラミング自体は去年の秋ぐらいに始めたので、まだ一年経っていませんが、
あまり成長が見られないな―と思いました。

自分はpaizaというWebサービスで問題を解きつつ、その言語に慣れていこうと考えているのですが、
問題がそもそも解けないのです。

Bランクまではいっているのですが、Aランクの問題が全くと言っていいほど解けません。
といってもまだ1,2問しか手を付けていませんが。
なんとなく解けなさそうだなと思って、そのまま敬遠している節があります。
最近は解き慣れていないからなのか、Bランクの問題すら怪しくなってきました。

趣味ぐらいの気持ちで始めているので、モチベーションが保てていないのか、
そもそもいろんなことに興味を持ちすぎて一つのことに集中できていないから
成長のスピードが遅いのか、周囲にプログラミングをやっている友人がいないので
切磋琢磨しあえないからなのか。

理由はいろいろ考えられますし、そのすべてが原因なような気もします。
原因がわかっているので改善点もわかっているはずなのに、
あまり改善しようと考えていないことが一番の問題な気もしています。

一つしか選択肢がないのであれば、その選択肢に集中できるのかもしれませんが、
自分で選択肢を増やして集中できなくしているのですから、世話がないです。

いつもここまで考えながら、最終的には「まあ、いっか」で済ましているので、
個人的にはそこまで重い悩みでもないのかなとも思います。

マイペースにのんびりというモットーを忘れずにやっていきたいものです。

エネルギーダイアグラム

Pythonソースコードを載せてみようかと思います。

大学の課題で必要だったので、エネルギーダイアグラムをmatplotlibで作りました。

以下にソースコードを載せます。物質名等はそれぞれ適当なものをお使いください。

#numpyとpyplotのimport
import numpy as np
import matplotlib.pyplot as plt



#各物質名を配列で与える(今回は便宜的にアルファベット)
name = ['A', 'B', 'C', 'D', 'E', 'F', 'G', 'H']
	

#LUMOのエネルギー準位(タプルでも配列でもかまいません)
LUMO = (-5.7, -2.0, -2.11, -2.06, -2.9, -3.4, -2.7, -2.73)


#(HOMOのエネルギー準位)ー(LUMOのエネルギー準位)
height = (-3.8, -3.5, -3.53, -3.65, -2.9, -2.4, -2.4, -3.95)

#プロットする領域の作成
fig = plt.figure(figsize = (8, 6))
ax = fig.add_subplot(1, 1, 1)


ind = np.arange(8)
width = 0.35
xgap = 0.3

#グラフの色用に0.0~0.7まで0.1刻みの配列を生成(任意)
color = list(map(lambda x:x/10, np.arange(len(name))))


'''
・パラメーターの補足
x座標は棒グラフのx座標を指定していますが、indは0〜7の配列、xgapは0.3、
また幅(width)は0.35なので、棒グラフは右から
0.3から0.65を塗りつぶす
1.3から1.65を塗りつぶす

となっていきます。

bottomを指定することでその部分から棒グラフを作ります。
例)
bottom = 10, 高さ = 10
ならy座標が10のところから更に10、つまり10〜20で棒グラフを作ります。
'''
ax.bar(ind+xgap, height, width, 
	bottom = LUMO, color = plt.cm.hsv(color), alpha = .5, edgecolor = 'w')



#graphの枠を消す
sihou = ('top', 'bottom', 'right', 'left')
for i in sihou:
	ax.spines[i].set_visible(False)



#Y軸についての設定
ax.yaxis.set_ticks_position('left')    #Y軸の座標を左のみ表示
ax.set_yticks(np.arange(10)-10)               #Y軸の目盛りの位置
ax.set_yticklabels((np.arange(10)-10))      #Y軸の目盛りのラベルの設定
ax.set_ylabel('Energy (eV)')                      #Y軸のラベルの設定


#X軸についての設定
ax.xaxis.set_ticks_position('none')   #X軸の目盛りを上下ともに非表示
ax.set_xticks(ind+xgap+width/2)      #X軸の目盛りの位置
ax.set_xticklabels(name)         #X軸の目盛りのラベルの設定


#HOMOの数値の表示
for x, y1, y2 in zip(ind+width/2+xgap, height, LUMO):
	ax.text(x, y1+y2, '%.2f'%(y1+y2), ha = 'center', va = 'top')

#LUMOの数値表示
for x, y in zip(ind+xgap+width/2, LUMO):
	ax.text(x, y-0.03, '%.2f'%(y), ha = 'center', va = 'bottom')



plt.show()
#画像として保存したい場合はplt.show()の代わりにsavefigメソッドで保存できます。以下に例を書きます。
#plt.savefig(filename = 'sample.png', dpi = 600)

f:id:jinpei0908:20160805231253p:plain

実際に実行してみるとこのような図が得られると思います。

気になっているもの

最近Linuxに興味があります。

なので基本はMacを使っているのですが、Linux用に
もう一台ノートパソコンを買おうかと迷っています。

今のところ気になっている機種としては、ASUSのVivobook E200HAという機種です。
hpやDELLの格安pcも考えたのですが、デザイン性という点で今のところは
この機種が一番ですね。購入したら、レビュー記事みたいなものも書いてみたいです。

全く話は変わりますが、8月の後半ぐらいにiPod 5.5gの分解をしようと思っているので、
またその記事も書けるようにしたいです。

やりたいことはたくさんあるのですが、あまり気力が追いついてないので、
まだまだ時間がかかりそうです。

Swiftのオプショナル型と型変換

paizaの標準入力のところでオプショナル型の変数が使われているのですが、
そもそもオプショナル型を理解していなかったのでここ数日調べたりしてました。

paizaは文字列を受け取るので、intもしくはdouble変換が必須になります。

調べてわかったこととして、Swift2のキャストはPythonに慣れている自分にとって比較的簡単でした。
Int(string)でString->Intとなるようです。試していないですが、Double変換も同様にできるのではないでしょうか。

ただキャストされた値はoptional int型という型の値で返されるようで、
数値計算を行う際はアンラップしてから用いることが必要なようです。

型キャストの参考URLを載せておきます。

qiita.com