RuntaScience diary

気象系データを扱う学生 旅が好きです

【データ解析】Pythonでデータ解析[基礎]ー数と文字・計算・配列・行列

f:id:RuntaScience:20200704182559p:plain



こんにちは

今日はpythonでデータ解析の基礎です

 

数と文字

主に用いられる型(type)

f:id:RuntaScience:20200704173342p:plain

 整数(int)
a = 4
type(a)
>>>int
 浮動小数点(float)
b = 4.4
type(b)
>>>float

 

b2 = 1/3
type(b2)
>>>float
 真偽(True or False)
c = True
type(c)
>>>True

 

文字列(str)
d = "NAME"
type(d)
>>>str

 

日付(datetime)
import pandas as pd
e = pd.to_datetime("2019-01-01 12:30")
print(e)
type(e)
>>>2019-01-01 12:30:00
pandas._libs.tslibs.timestamps.Timestamp

 

リスト(list)
f = [1, 2, 3, 4]
type(f)
>>>list

 

 辞書
g = {"A1":1, "A2":2, "A3":3, "A5":4}
type(g)
>>>dict

 

タプル
h = (1, 2, 3, 4)
type(h)
>>>tuple

 

セット
i = {1, 2, 3, 4}
type(i)
>>>set

 

配列(array)
import numpy as np
j = np.arange(1,5,1)
type(j)
>>>numpy.ndarray

 

関数
def my_name(name):
    print(name)
my_name("Alex")    
type(my_name)
>>>Alex
function

 

 

計算

 基本的な計算から、行列計算までです

 

加法・減法・乗法・除法

1 + 4
>>>5

 

4 - 1
>>>3

 

11 * 12
>>>132

 

33 / 3
>>>11.0

 

11 % 2
>>>1

 

配列

 np.arange(x, y, n)

xからyまでのn間隔の配列の作成

注意するのは、y-1しか数が並ばないこと。

a = np.arange(1, 10, 1)
a
>>>array([1, 2, 3, 4, 5, 6, 7, 8, 9])

 

a2 = np.array([1, 2, 3, 4, 5, 6, 7, 8, 9])
a2
>>>array([1, 2, 3, 4, 5, 6, 7, 8, 9])

 

.reshape(行, 列)で配列の次元を変更できます。

#2次元配列作成
b = np.arange(1, 51, 1).reshape(5, 10)
b
>>>array([[ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10],
[11, 12, 13, 14, 15, 16, 17, 18, 19, 20],
[21, 22, 23, 24, 25, 26, 27, 28, 29, 30],
[31, 32, 33, 34, 35, 36, 37, 38, 39, 40],
[41, 42, 43, 44, 45, 46, 47, 48, 49, 50]])

 

.reshape(-1,)で1次元配列に戻せます

b2 = b.reshape(-1,)
b2
>>>array([ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17,
18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34,
35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50])

 

最後に配列の情報を確認しておきましょう。

print(b.shape) #配列の形
print(b.ndim) #配列の次元
print(b.size) #配列のサイズ
>>>(5, 10)
>>>2
>>>50

 

行列計算

基礎

 

f:id:RuntaScience:20200704180841p:plain



A = np.array([[2, 2], [2, 4]])
A
>>>array([[2, 2],
[2, 4]])

 

A + 10
>>>array([[12, 12],
[12, 14]])

 

A + A
>>>array([[4, 4],
[4, 8]])

 

A * 3
>>>array([[ 6, 6],
[ 6, 12]])

 

 ※行列の掛け算ではなく、要素の掛け算である

A * A
>>>array([[ 4, 4],
[ 4, 16]])

 

行列の積(3種類の計算方法)

A @ A
np.dot(A, A)
A.dot(A)
>>>array([[ 8, 12],
[12, 20]])

 

転置行列・逆行列単位行列

 

f:id:RuntaScience:20200704180900p:plain

np.transpose(A)
>>>array([[2, 2],
[2, 4]])

 

f:id:RuntaScience:20200704180952p:plain

inv_A = np.linalg.inv(A)
inv_A
>>>array([[ 1. , -0.5],
[-0.5, 0.5]])
 
A.dot(inv_A)
# np.dot(A, inv_A)
>>>array([[1., 0.],
[0., 1.]])

 

逆行列が求まらない場合は単位行列は出ない

B = np.array([[1, 2, 3], [4, 5, 6], [7, 8, 9]]) B
>>>array([[1, 2, 3],
[4, 5, 6],
[7, 8, 9]])

#逆行列
inv_B = np.linalg.inv(B) inv_B
>>>array([[ 3.15251974e+15, -6.30503948e+15, 3.15251974e+15],
[-6.30503948e+15, 1.26100790e+16, -6.30503948e+15],
[ 3.15251974e+15, -6.30503948e+15, 3.15251974e+15]])
#元の行列×逆行列
B.dot(inv_B)
>>>array([[ 0. , 1. , -0.5],
[ 0. , 2. , -1. ],
[ 0. , 3. , 2.5]])

 ⇑単位行列が求まっていない

それは、元の行列の行列式≠0を満たしていないからである

int(np.linalg.det(B))
>>>0
 行列式

f:id:RuntaScience:20200704181041p:plain

 np.linalg.det(A)
>>>4.0

 

固有値固有ベクトル

f:id:RuntaScience:20200704181016p:plain



 

A = np.array([[2, 2], [2, 4]])
A
>>>array([[2, 2],
[2, 4]])

 

w, v = np.linalg.eig(A)
print(w) #固有値
print(v) #固有ベクトル
>>>[0.76393202 5.23606798]
[[-0.85065081 -0.52573111]
[ 0.52573111 -0.85065081]]

 

 それでは🌏

 

【Pandas】 データをファイルに格納(保存; WRITE)

f:id:RuntaScience:20200703220436p:plain

こんにちは。今日は作成したデータを保存する方法です。

 

 

データフレーム

まずはモジュールをインポートします。

import pandas as pd

 

使用するデータは、以下のデータフレームです。

print(df)

>>>

Year Month Day Data
0 2019 1 1 12
1 2019 2 1 14
2 2019 3 1 13
3 2019 4 1 12
4 2019 5 1 13
5 2019 6 1 11
6 2019 7 1 14
7 2019 8 1 12
8 2019 9 1 14
9 2019 10 1 14
10 2019 11 1 11
11 2019 12 1 15

テキストファイル

 indexまで保存されるので、読みこみの時は、indexを指定しましょう

保存時にindexを除きたい場合は、

df.to_csv("XXX.txt", index=False)

としましょう。

カンマ区切り
#データの保存
df.to_csv("XXX.txt") #確認 pd.read_csv("XXX.txt", index_col=0)

 

 

タブ区切り
#データの保存
df.to_csv("XXX.txt",sep="\t") #確認 pd.read_table("XXX.txt",index_col=0)

 

 

エクセルファイル

#データの保存
df.to_excel("XXX.xlsx",sheet_name="X") #確認
pd.read_excel("XXX.xlsx",index_col=0,sheet_name="X")

 

 

複数データを同時に

 複数のデータフレームを1つのファイルにシートを分けて保存するには、ExcelWriterを使います。

例として、データフレームをdf1, df2, df3とします

path = "XXX.xlsx"
with pd.ExcelWriter(path) as writer:
    df1.to_excel(writer, sheet_name = "sheet1")
    df2.to_excel(writer, sheet_name = "sheet2")
    df3.to_excel(writer, sheet_name = "sheet3")

 

バイナリデータ(配列;Array)

まずはモジュールをインポートします。

import numpy as np

 今回は1次元の配列データと2次元の配列データを保存します。

lon = np.arange(-180,180,0.1)
lat = np.arange(-90, 90, 0.1)
two_dim = np.arange(0,150,1).reshape(10,15)
print(lon, lat, two_dim)
>>>[-180.  -179.9 -179.8 ...  179.7  179.8  179.9]
>>>[-90. -89.9 -89.8 ... 89.7 89.8 89.9]
>>>[[ 0 1 ... 12 13 14][ 15 16 ... 27 28 29]...
...[120 121 ... 132 133 134] [135 136 ... 147 148 149]]

 

保存します。

np.save("XXX1.npy", lon)
np.save("XXX2.npy", lat)
np.save("XXX3.npy", two_dim)

 読み込んでデータがしっかり入っていることを確認しましょう

np.load("XXX1.npy")
>>>[-180. -179.9 -179.8 ... 179.7 179.8 179.9]

 

読み込みに関しては前の記事で紹介しています。

runtascience.hatenablog.com

 

 それでは🌏

 

【Pandas】ファイルをデータフレームに格納(読み込み; READ)

f:id:RuntaScience:20200703220402p:plain

こんにちは。今日はファイルの読み込みについてです。

 

 

テキストファイル

まずはモジュールをインポートします。

import numpy as np

カンマ区切り

pd.read_csv("XXX.txt") 

カンマで区切ってあるテキストファイルをインポートします。

データ⇓

Year, Month, Day, Data
2019, 1, 1, 12
2019, 2, 1, 14
2019, 3, 1, 13
2019, 4, 1, 12
2019, 5, 1, 10
2019, 6, 1, 10
2019, 7, 1, 15
2019, 8, 1, 12
2019, 9, 1, 10
2019, 10, 1, 12
2019, 11, 1, 10
2019, 12, 1, 12

 

df = pd.read_csv("XXX.txt")
df

 

  Year Month Day Data
0 2019 1 1 12
1 2019 2 1 14
2 2019 3 1 13
3 2019 4 1 12
4 2019 5 1 10
5 2019 6 1 10
6 2019 7 1 15
7 2019 8 1 12
8 2019 9 1 10
9 2019 10 1 12
10 2019 11 1 10
11 2019 12 1 12

 

タブ区切り

pd.read_table("XXX.txt")

タブ区切りのテキストファイルも同様にデータフレームに格納できます

Year	Month	Day	Data
2019	1	1	12
2019	2	1	14
2019	3	1	13
2019	4	1	12
2019	5	1	13
2019	6	1	11
2019	7	1	14
2019	8	1	12
2019	9	1	14
2019	10	1	14
2019	11	1	11
2019	12	1	15

 1)

df = pd.read_table("XXX.txt")
df

 2)

df = pd.read_csv("XXX.txt",sep="\t")
df

 

  Year Month Day Data
0 2019 1 1 12
1 2019 2 1 14
2 2019 3 1 13
3 2019 4 1 12
4 2019 5 1 10
5 2019 6 1 10
6 2019 7 1 15
7 2019 8 1 12
8 2019 9 1 10
9 2019 10 1 12
10 2019 11 1 10
11 2019 12 1 12

 

エクセルファイル

 エクセルファイルも同様のデータを使います。

基本

Year Month Day Data
2019 1 1 12
2019 2 1 14
2019 3 1 13
2019 4 1 12
2019 5 1 13
2019 6 1 11
2019 7 1 14
2019 8 1 12
2019 9 1 14
2019 10 1 14
2019 11 1 11
2019 12 1 15

 

df = pd.read_excel("XXX.xlsx")
df

シート名・インデックスを指定したい場合

sheet ="b"でインデックスをidxで指定する場合は、

f:id:RuntaScience:20200702112923p:plain

df = pd.read_excel("XXX.xlsx", sheet_name="b",index_col=0)
df

 

  Year Month Day Data
idx        
1 2019 1 1 12
2 2019 2 1 14
3 2019 3 1 13
4 2019 4 1 12
5 2019 5 1 13
6 2019 6 1 11
7 2019 7 1 14
8 2019 8 1 12
9 2019 9 1 14
10 2019 10 1 14
11 2019 11 1 11
12 2019 12 1 15

 

データの一部のみ使いたい

Year Month Day Data_x1 Data_x2 Data_y1 Data_y2
2019 1 1 12 12 12 12
2019 2 1 14 14 14 14
2019 3 1 13 13 13 13
2019 4 1 12 12 12 12
2019 5 1 13 13 13 13
2019 6 1 11 11 11 11
2019 7 1 14 14 14 14
2019 8 1 12 12 12 12
2019 9 1 14 14 14 14
2019 10 1 14 14 14 14
2019 11 1 11 11 11 11
2019 12 1 15 15 15 15
1)データを含む
include=["Data_x1"]
df = pd.read_excel("XXX.xlsx", sheet_name="c",usecols=include)
df
Data_x1
0 12
1 14
2 13
3 12
4 13
5 11
6 14
7 12
8 14
9 14
10 11
11 15
2)データを抜く

 exclude=["Data_x2", "Data_y2"] #抜く列 df = pd.read_excel("XXX.xlsx", sheet_name = "c",usecols = lambda x: x not in exclude) df
Year Month Day Data_x1 Data_y1
0 2019 1 1 12 12
1 2019 2 1 14 14
2 2019 3 1 13 13
3 2019 4 1 12 12
4 2019 5 1 13 13
5 2019 6 1 11 11
6 2019 7 1 14 14
7 2019 8 1 12 12
8 2019 9 1 14 14
9 2019 10 1 14 14
10 2019 11 1 11 11
11 2019 12 1 15 15

 

 

 3)header飛ばし
data:2019/1/1    
Site:Japan      
       
Year Month Day Data
2019 1 1 12
2019 2 1 14
2019 3 1 13
2019 4 1 12
2019 5 1 13
2019 6 1 11
2019 7 1 14
2019 8 1 12
2019 9 1 14
2019 10 1 14
2019 11 1 11
2019 12 1 15
df = pd.read_excel("XXX.xlsx", sheet_name = "a",header = 3)
df

 

Year Month Day Data
0 2019 1 1 12
1 2019 2 1 14
2 2019 3 1 13
3 2019 4 1 12
4 2019 5 1 13
5 2019 6 1 11
6 2019 7 1 14
7 2019 8 1 12
8 2019 9 1 14
9 2019 10 1 14
10 2019 11 1 11
11 2019 12 1 15

 

netCDFファイル

 まずはモジュールをインポート

from netCDF4 import Dataset

 

nc = Dataset("XXX.nc4", mode="r")
nc
<データの情報が出てくる>・・・・

 データの情報を基に、データをarrayにする。

data = nc.variables["dataname"][:].data #1次元データの場合
data
>>>array([100,120,122,111,92,222,…, 128, 100])

 

 それでは🌏

Lightroomで動物の背景を黒くする方法

f:id:RuntaScience:20200628094826j:plain

こんにちは!
今回は、写真の編集方法に関してです。

 

 

撮影

まずは編集前です。

f:id:RuntaScience:20200628094804p:plain

シャッタースピード:1/800、f:5.6、ISO:1000

 

背景を黒くすることを考えて、主役の動物が映えるように撮ります。

動物がぶれないようにシャッタースピードを上げます。

 

 編集

ライト

f:id:RuntaScience:20200628094837j:plain

コントラストを高めて、ハイライト、シャドウ、黒レベルをマイナスに落とすと

主役が映えるようになります。

ハイライトを下げると、羽などの陰がシャープになります。

シャドウを下げると主に背景が黒みがかります。

黒レベルを下げると、全体的に黒くなり、白が映えます。

 

カラー

 

f:id:RuntaScience:20200628094844j:plain

カラーは生き物によって変えましょう。

過度な彩度変化は施さなくても大丈夫だと思います。

より美しく見えるように調節します。

 

作品例

f:id:RuntaScience:20200628094817j:plain

対象が白で無い場合も編集可能です。

また、Rawで撮らなくても上記のように編集ができます。

 

 

大切なこと

一番大切なことは、編集後をイメージすることだと思います。

背景を黒くするために撮った写真は、編集すると美しいですが、編集前は色が薄い写真となります。したがって、撮る段階が一番大切だと感じます。

 

それでは🌏

 

 

 

【Matplotlib】Python Format文~必要なものだけ厳選(理系)

こんにちは!

今回は、pythonでよく用いるformat文についてです

 

 

使い方

基本的な使い方は簡単です。

"{}"の中身を.format()で書き入れましょう

"{}".format(2019)
>>>'2019'

 

1つだけではなく、複数の文字や数を入れられます。

0番から始まる連番で指定すると、その数が入ります。

"I'm {0} {1}.".format("Noah", "Saito")
>>>"I'm Noah Saito."

 

具体例

次によく使うものを具体例で見ていきましょう。

小数点

小数点は「f」で表現します。fの前に何桁か指定できます。デフォルトは6桁です。

a = 0.2183
"{0:f} || {0:.1f}".format(a)
>>>'0.218300 || 0.2'

 

同様に指数表記のEもできます。こちらもデフォルトは6桁です。eが大文字か小文字かも指定できます。

a = 0.2183
"{0:e} || {0:.1e} || {0:.1E}".format(a)
>>>'2.183000e-01 || 2.2e-01 || 2.2E-01'

 

日にち

それぞれの日付のデータを使って以下のように表すことができます。

year, month, day = 2019, 1, 1
"{0}-{1}-{2}".format(year, month, day)
>>>'2019-1-1'

 

日付を'2019-01-01'のような桁数指定をしたい場合は、以下のように

「位置:0+桁数d」としましょう。(dは10整数である)

year, month, day = 2019, 1, 1
"{0:04d}-{1:02d}-{2:02d}".format(year, month, day)
>>>'2019-01-01'

 

さらに、モジュールのdatetimeを用いて表現できます。

import datetime
time = datetime.datetime(2019, 1, 1, 1, 1, 30)
"{:%Y-%m-%d %H:%M:%S}".format(time)
'2019-01-01 01:01:30'

 

ちなみに、月をJan, Feb...のようにしたい場合は、「%b」と指定します。

import datetime
for i in range(12):
    time = datetime.datetime(2019, i+1, 1)
    print("{:%b}".format(time))
>>>Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec

 

n進数

 2進数(binary number)、8進数(octal number)、10進数(decimal number)、16進数(hexadecimal number)があります。

binary, octal, decimal, hexadecimal = 30, 30, 30, 30
"{0:b}-{1:o}-{2:d}-{3:x}(or{3:X})".format(binary, octal, decimal, hexadecimal)
>>>'11110-36-30-1e(or1E)'

 

 最後にパーセント表示です。100倍されることに注意してください。

そして、桁数も変更できます。デフォルトは6桁です。

a = 0.2183
"{0:%} || {0:.0%} || {0:.2%}".format(a)
>>>'21.830000% || 22% || 21.83%'

 

 

さらに詳しく

今回の記事はこちらを参考にして、理系が用いるものを厳選して紹介しました。

docs.python.org

 

 

 

それでは

【Numpy&Matplotlib】 Python 軸を日付フォーマットに変更

こんにちは今日はx軸を日にちのフォーマットに変更する方法です。

 

 

DataFlame

まずは使用するデータフレームをファイルから読み込んでください。

今回私は適当に作成したデータを使います。

 

print(df)
  Year Month Day Hour Minute Data
0 2019 1 1 0 1 1.683375
1 2019 1 1 0 6 1.732797
2 2019 1 1 0 11 0.985744
3 2019 1 1 0 16 1.522657
4 2019 1 1 0 21 0.726131
... ... ... ... ... ... ...
105115 2019 12 31 23 36 1.442926
105116 2019 12 31 23 41 1.532434
105117 2019 12 31 23 46 1.513058
105118 2019 12 31 23 51 0.594683
105119 2019 12 31 23 56 0.767968

105120 rows × 6 columns

 

1日当たりのDataの平均値を時系列プロットしてみます

#日平均
import calendar
xdata = []
year=2019
for j in range(12):
    month=j+1
    x=calendar.monthrange(year, month)[1] #*1
    df2 = df.loc[df["Month"]==month]
    for i in range(x):
        day = i + 1
        xdata0 = df2.loc[df2["Day"]==day]["Data"].mean()
        xdata.append(xdata0)

 Keys

1) year年month月の日数を取ることができる。

例えばyear=2019 month=1 の時、x=31となる。

 

それではグラフを書いてみます。横軸はDN(Day Number)です。

import matplotlib.pyplot as plt
#グラフ作成
fig = plt.figure(figsize=(20,5))
plt.rcParams["font.size"] = 16
ax = plt.subplot(111)

ax.plot(np.arange(1,366), xdata)

ax.set_xlabel("DN")
ax.set_ylabel("Data")

ax.set_xlim(0,365)

plt.show()

fig.savefig("XXX.png",format="png", dpi=330)

 

f:id:RuntaScience:20200624201255p:plain

 

DN⇒Datetime

次に横軸を日付にします。

 

time = []
year = 2019
for i in range(12):
    month = i + 1
    x=calendar.monthrange(year, month)[1]
    for j in range(x):
        day = j + 1
        t = "{0:04d}-{1:02d}-{2:02d}".format(year, month, day) #1*
        time.append(pd.to_datetime(t)) #*2

 

Keys

1) format文⇓

 

2)pd.to_datetime("2019-01-01 01:30:00:00")⇒Timestamp("2019-01-01 01:30:00:00")

オブジェクト⇒datetimeに変換されます

 

 

グラフ

 

#データの選択
x = time
y = xdata

#グラフ作成
fig = plt.figure(figsize=(20,5))
plt.rcParams["font.size"] = 16
ax = plt.subplot(111)

ax.plot(x, y)

#ラベル設定
ax.set_title(" ")
ax.set_ylabel("data")
ax.set_xlabel("Time")

#軸の設定 *1
ax.minorticks_on() 
ax.tick_params(axis="both", which="major",direction="in",length=7,width=2,top="on",right="on")
ax.tick_params(axis="both", which="minor",direction="in",length=4,width=1,top="on",right="on")
ax.xaxis.set_major_formatter(DateFormatter("%b-%d"))
ax.xaxis.set_major_locator(mdates.MonthLocator(interval=2)) 
ax.xaxis.set_minor_locator(mdates.MonthLocator(interval=1)) 

#範囲設定
ax.set_xlim(datetime.datetime(2019, 1, 1), datetime.datetime(2019, 12, 31))

plt.show()

fig.savefig("XXX.png",format="png", dpi=330)

 

f:id:RuntaScience:20200624201912p:plain

Keys

1)軸の設定

 

runtascience.hatenablog.com

 

 

それでは 🌏

【Science】 Matplotlibで振り子ー二重振り子 カオスを知る

こんにちは!
今日は二重振り子でカオスを見てみたいと思います!

 

単振り子に基礎的なコードを載せています。

 

 

runtascience.hatenablog.com

 

 

 

 

 二重振り子

ドキュメント

matplotlib.org

 

モジュール

まずは必要なモジュールです。

import numpy as np
import matplotlib.pyplot as plt
import scipy.integrate as integrate
import matplotlib.animation as animation

 

軌跡

 まずは二重振り子の軌跡を描いてみます。

 

%matplotlib nbagg
#物理量設定
G = 9.8 #重力加速度(m/s^2)
L1 = 1.0  #振り子(上)の長さ(m)
L2 = 1.0  #振り子(下)の長さ(m)
M1 = 1.0  #振り子(上)の重さ(kg)
M2 = 1.0  #振り子(下)の重さ(kg)


def derivs(state, t):

    dydx = np.zeros_like(state)
    dydx[0] = state[1]

    delta = state[2] - state[0]
    den1 = (M1+M2) * L1 - M2 * L1 * np.cos(delta) * np.cos(delta)
    dydx[1] = ((M2 * L1 * state[1] * state[1] * np.sin(delta) * np.cos(delta)
                + M2 * G * np.sin(state[2]) * np.cos(delta)
                + M2 * L2 * state[3] * state[3] * np.sin(delta)
                - (M1+M2) * G * np.sin(state[0]))
               / den1)

    dydx[2] = state[3]

    den2 = (L2/L1) * den1
    dydx[3] = ((- M2 * L2 * state[3] * state[3] * np.sin(delta) * np.cos(delta)
                + (M1+M2) * G * np.sin(state[0]) * np.cos(delta)
                - (M1+M2) * L1 * state[1] * state[1] * np.sin(delta)
                - (M1+M2) * G * np.sin(state[2]))
               / den2)

    return dydx

#初期値
dt = 0.05 #時間間隔
t = np.arange(0, 20, dt) #時間間隔分
th1 = 120.0 #振り子(上)初期角度
w1 = 0.0 #振り子(上)角速度
th2 = -10.0 #振り子(下)初期角度
w2 = 0.0 #振り子(下)角速度

state1 = np.radians([th1, w1, th2, w2]) # 初期状態

#微分方程式を解く
y01 = integrate.odeint(derivs, state1, t)


x1 = L1 * np.sin(y01[:, 0])
y1 = -L1 * np.cos(y01[:, 0])
x2 = L2 * np.sin(y01[:, 2]) + x1
y2 = -L2 * np.cos(y01[:, 2]) + y1

#--------------------グラフ-----------------------
fig = plt.figure()
ax = fig.add_subplot(111, autoscale_on=False, xlim=(-2, 2), ylim=(-2, 2))
ax.set_aspect("equal")
ax.grid()

line, = ax.plot([], [], "o-", lw=2)
locus, = ax.plot([], [], "r-", linewidth=2) #軌跡用
time_template = "time = %.1fs"
time_text = ax.text(0.05, 0.9, "", transform=ax.transAxes)

xlocus, ylocus = [], []
def init():
    line.set_data([], [])
    locus.set_data([], [])
    time_text.set_text("")
    return line,locus, time_text


def animate(i):
    thisx1 = [0, x1[i], x2[i]]
    thisy1 = [0, y1[i], y2[i]]
    xlocus.append(x2[i])
    ylocus.append(y2[i])

    line.set_data(thisx1, thisy1)
    locus.set_data(xlocus, ylocus)
    time_text.set_text(time_template % (i*dt))
    return line,locus, time_text



ani = animation.FuncAnimation(fig, animate, range(1, len(y01)),
                              interval=dt*1000, blit=True, init_func=init)
plt.show()
# ani.save("XXX.gif", writer="pillow", fps=20)

 

youtu.be

 

 

 

2個

 次にいきなり複数の振り子にいくのはなんなので、2つの振り子を描写してみます。

 

%matplotlib nbagg
#物理量設定
G = 9.8 #重力加速度(m/s^2)
L1 = 1.0  #振り子(上)の長さ(m)
L2 = 1.0  #振り子(下)の長さ(m)
M1 = 1.0  #振り子(上)の重さ(kg)
M2 = 1.0  #振り子(下)の重さ(kg)


def derivs(state, t):

    dydx = np.zeros_like(state)
    dydx[0] = state[1]

    delta = state[2] - state[0]
    den1 = (M1+M2) * L1 - M2 * L1 * np.cos(delta) * np.cos(delta)
    dydx[1] = ((M2 * L1 * state[1] * state[1] * np.sin(delta) * np.cos(delta)
                + M2 * G * np.sin(state[2]) * np.cos(delta)
                + M2 * L2 * state[3] * state[3] * np.sin(delta)
                - (M1+M2) * G * np.sin(state[0]))
               / den1)

    dydx[2] = state[3]

    den2 = (L2/L1) * den1
    dydx[3] = ((- M2 * L2 * state[3] * state[3] * np.sin(delta) * np.cos(delta)
                + (M1+M2) * G * np.sin(state[0]) * np.cos(delta)
                - (M1+M2) * L1 * state[1] * state[1] * np.sin(delta)
                - (M1+M2) * G * np.sin(state[2]))
               / den2)

    return dydx

dt = 0.05
t = np.arange(0, 20, dt)

th1 = 120.0
th12 = 120.1
w1 = 0.0
th2 = -10.0
w2 = 0.0

#初期状態
state1 = np.radians([th1, w1, th2, w2])
state2 = np.radians([th12, w1, th2, w2])

#微分方程式を解く
y01 = integrate.odeint(derivs, state1, t)
y02 = integrate.odeint(derivs, state2, t)

x1 = L1 * np.sin(y01[:, 0])
y1 = -L1 * np.cos(y01[:, 0])
x2 = L2 * np.sin(y01[:, 2]) + x1
y2 = -L2 * np.cos(y01[:, 2]) + y1

x3 = L1 * np.sin(y02[:, 0])
y3 = -L1 * np.cos(y02[:, 0])
x4 = L2 * np.sin(y02[:, 2]) + x3
y4 = -L2 * np.cos(y02[:, 2]) + y3

fig = plt.figure()
ax = fig.add_subplot(111, autoscale_on=False, xlim=(-2, 2), ylim=(-2, 2))
ax.set_aspect("equal")
ax.grid()

line, = ax.plot([], [], "o-", lw=2)
line2, = ax.plot([], [], "o-", lw=2)
time_template = "time = %.1fs"
time_text = ax.text(0.05, 0.9, "", transform=ax.transAxes)


def init():
    line.set_data([], [])
    line2.set_data([], [])
    time_text.set_text("")
    return line,line2, time_text


def animate(i):
    thisx1 = [0, x1[i], x2[i]]
    thisy1 = [0, y1[i], y2[i]]
    thisx2 = [0, x3[i], x4[i]]
    thisy2 = [0, y3[i], y4[i]]

    line.set_data(thisx1, thisy1)
    line2.set_data(thisx2, thisy2)
    time_text.set_text(time_template % (i*dt))
    return line,line2, time_text



ani = animation.FuncAnimation(fig, animate, range(1, len(y01)),
                              interval=dt*1000, blit=True, init_func=init)
plt.show()
#ani.save("XXX.gif", writer="pillow", fps=20)

 

youtu.be

 

 

カオス

 最後にカオスを描写してみます。

先ほどよりも振り子数が一気に増えます。

 

%matplotlib nbagg
#物理量設定
G = 9.8 #重力加速度(m/s^2)
L1 = 1.0  #振り子(上)の長さ(m)
L2 = 1.0  #振り子(下)の長さ(m)
M1 = 1.0  #振り子(上)の重さ(kg)
M2 = 1.0  #振り子(下)の重さ(kg)


def derivs(state, t):

    dydx = np.zeros_like(state)
    dydx[0] = state[1]

    delta = state[2] - state[0]
    den1 = (M1+M2) * L1 - M2 * L1 * np.cos(delta) * np.cos(delta)
    dydx[1] = ((M2 * L1 * state[1] * state[1] * np.sin(delta) * np.cos(delta)
                + M2 * G * np.sin(state[2]) * np.cos(delta)
                + M2 * L2 * state[3] * state[3] * np.sin(delta)
                - (M1+M2) * G * np.sin(state[0]))
               / den1)

    dydx[2] = state[3]

    den2 = (L2/L1) * den1
    dydx[3] = ((- M2 * L2 * state[3] * state[3] * np.sin(delta) * np.cos(delta)
                + (M1+M2) * G * np.sin(state[0]) * np.cos(delta)
                - (M1+M2) * L1 * state[1] * state[1] * np.sin(delta)
                - (M1+M2) * G * np.sin(state[2]))
               / den2)

    return dydx

dt = 0.05
t = np.arange(0, 20, dt)


th1s = np.arange(120.0,120.01,0.0001)
w1 = 0.0
th2 = -10.0
w2 = 0.0


#初期状態
states=[]
for th1 in th1s:
    state = np.radians([th1, w1, th2, w2])
    states.append(state)
    
#微分方程式を解く
ys=[]
for state in states:
    y = integrate.odeint(derivs, state, t)
    ys.append(y)
    
x1s,x2s,y1s,y2s=[],[],[],[]
for y in ys:
    x1 = L1 * np.sin(y[:, 0])
    y1 = -L1 * np.cos(y[:, 0])
    x2 = L2 * np.sin(y[:, 2]) + x1
    y2 = -L2 * np.cos(y[:, 2]) + y1
    x1s.append(x1)
    y1s.append(y1)
    x2s.append(x2)
    y2s.append(y2)

fig = plt.figure()
ax = fig.add_subplot(111, autoscale_on=False, xlim=(-2, 2), ylim=(-2, 2))
ax.set_aspect("equal")
ax.grid()

lines=[]
for i in range(len(th1s)):
    line, = ax.plot([], [], "o-", lw=2)
    lines.append(line,)
time_template = "time = %.1fs"
time_text = ax.text(0.05, 0.9, "", transform=ax.transAxes)


def init():
    for line in lines:
        line.set_data([], [])
    time_text.set_text('')
    return lines, time_text


def animate(i):
    for j in range(len(lines)):
        line = lines[j]
        thisx1 = [0, x1s[j][i], x2s[j][i]]
        thisy1 = [0, y1s[j][i], y2s[j][i]]

        line.set_data(thisx1, thisy1)
    time_text.set_text(time_template % (i*dt))
    return lines, time_text


ani = animation.FuncAnimation(fig, animate, range(1, len(y)),
                              interval=dt*1000, blit=True, init_func=init)
plt.show()

# ani.save("XXX.gif", writer="pillow", fps=20)

 

 

youtu.be

 

 

 

それでは🌏

【Science】 Matplotlibで振り子ー単振り子

こんにちは

今日は関数を使って、単振り子をアニメーションを作成したいと思います!

 アニメーションの基礎は前の記事を参照してください!

 

runtascience.hatenablog.com

 

 

 

微分方程式

単振り子を描写するのに関数が必要なので書き方を確認しましょう

docs.scipy.org

モジュール

 

from scipy.integrate import solve_ivp
import matplotlib.pyplot as plt
import numpy as np

 

解く

それでは、solve_ivpで指数関数的減衰を解いてみます。

 指数関数的減衰は半減期の計算で使われますね

https://www.nli-research.co.jp/report/detail/id=58700?site=nli

 

dy dt = -λ y

 

# 指数関数的減衰
def exponential_decay(t, y):
    return -0.5 * y

t_span = [0, 10] #tの範囲
y0 = [2, 4, 8] #y初期値
t_eval = np.arange(t_span[0], t_span[-1], 0.1) #tの間隔
sol = solve_ivp(exponential_decay, t_span, y0, t_eval=t_eval) #方程式を解く

 

解(sol)の中身を確認します。

print(sol.t)
⇒[0. 0.1 0.2 0.3…9.7 9.8 9.9]
print(sol.y)
⇒[[2. 1.90245885 1.809668…0.01492886 0.01420166]
[4. 3.8049177 3.619336…0.02985772 0.02840332]
[8. 7.6098354 7.238672…0.05971543 0.05680663]]

 tに対するyが作成されていることがわかります。

 

描写

それでは描写してみます

fig, ax = plt.subplots()
ax.plot(sol.t, sol.y[0])
ax.plot(sol.t, sol.y[1])
ax.plot(sol.t, sol.y[2])

ax.set_xlabel("T")
ax.set_ylabel("Y-axis")

ax.set_xlim(t_span[0],t_span[-1])
ax.set_ylim(0, 9)

plt.show()

#保存
#fig.savefig("XXX.png", format="png", dpi=330)

 

f:id:RuntaScience:20200621150622p:plain

 

 

単振り子

それでは単振り子のアニメーション作成してみます。

以下を参考に作成しました。

qiita.com

 

モジュール

まずはモジュールをインポートします

from scipy.integrate import solve_ivp
from matplotlib.animation import FuncAnimation
import matplotlib.pyplot as plt
import numpy as np

 

 

単振り子

 

%matplotlib nbagg
G = 9.8  # 重力加速度(m/s^2)
L = 1.0  # 振り子の長さ(m)

# 運動方程式を解く
def eom(t, state):
    dydt = np.zeros_like(state)
    dydt[0] = state[1]
    dydt[1] = -(G/L)*np.sin(state[0])
    return dydt

#設定
t_span = [0,20] #時間 (s)
dt = 0.05# 時間の間隔 (s)
t = np.arange(t_span[0], t_span[-1], dt)# 時間の間隔のarray作成

#初期状態設定
th1 = 45.0# 角度 [deg]
w1 = 0.0 # 初期角速度 [deg/s]
state = np.radians([th1, w1])# 初期状態

#微分方程式を解く
sol = solve_ivp(eom, t_span, state, t_eval=t)
theta = sol.y[0] #y[0]=θ、y[1]=ω

x = L * np.sin(theta)       
y = -L * np.cos(theta)      

#ーーーーーーグラフーーーーーーー
fig, ax = plt.subplots()

line, = ax.plot([], [], "o-", linewidth=2) 
time_template = "time = %.1fs"
time_text = ax.text(0.05, 0.9, " ", transform=ax.transAxes)

def init():
    line.set_data([], [])
    time_text.set_text("")
    return line, time_text

def animate(i):
    thisx = [0, x[i]]
    thisy = [0, y[i]]
    line.set_data(thisx, thisy)
    time_text.set_text(time_template % (i*dt))
    return line, time_text


ani = FuncAnimation(fig, animate, frames=np.arange(0, len(t))
                    , interval=25, blit=True,init_func=init)

ax.set_xlim(-L-0.5,L+0.5)
ax.set_ylim(-L-0.5,L+0.5)
ax.set_aspect("equal")
ax.grid()

plt.show()

#ani.save("XXX.gif", writer="pillow", fps=20)

 

 

youtu.be

 

時間変化

次に単振り子の角度、x,  yの時間変化をプロットしてみます

 

fig = plt.figure(figsize=(10,5))
ax1 = plt.subplot(111)
ax2 = ax1.twinx()

ax1.plot(sol.t, sol.y[0], label="$\\theta$")
ax2.plot(sol.t, x , color="r", linestyle="--",label="x")
ax2.plot(sol.t, y , color="g", linestyle="--",label="y")

ax1.set_yticks(np.array([-np.pi, -(1/3)*np.pi, -(1/4)*np.pi, -(1/6)*np.pi, 0,(1/6)*np.pi,(1/4)*np.pi,(1/3)*np.pi,np.pi]))
ax1.set_yticklabels(["-$\pi$","-1/3$\pi$","-1/4$\pi$","-1/6$\pi$", "0","1/6$\pi$","1/4$\pi$","1/3$\pi$","$\pi$"])
ax1.set_ylabel("$\\theta$")
ax2.set_yticks(np.array([-1,-(1/2)*np.sqrt(3),-(1/2)*np.sqrt(2),-(1/2)*np.sqrt(1),0,(1/2)*np.sqrt(1),(1/2)*np.sqrt(2),(1/2)*np.sqrt(3),1]))
ax2.set_yticklabels(["$-$1","$-\sqrt{\\frac{3}{2}}$","$-\sqrt{\\frac{2}{2}}$","$-{\\frac{1}{2}}$", "0","${\\frac{1}{2}}$","$\sqrt{\\frac{2}{2}}$","$\sqrt{\\frac{3}{2}}$","1"])
ax2.set_ylabel("X, Y")
ax1.set_xlabel("T")

ax1.set_xlim(t_span[0],t_span[-1])
ax1.set_ylim(-(1/3)*np.pi,(1/3)*np.pi)

#凡例
h1, l1 = ax1.get_legend_handles_labels()
h2, l2 = ax2.get_legend_handles_labels()
ax1.legend(h1+h2, l1+l2, ncol=3, fontsize=12)

plt.show()

#保存
#fig.savefig("XXX.png", format="png", dpi=330)

 

f:id:RuntaScience:20200621174250p:plain

 

単振り子の軌跡

 

%matplotlib nbagg
G = 9.8  # 重力加速度(m/s^2)
L = 1.0  # 振り子の長さ(m)

# 運動方程式を解く
def eom(t, state):
    dydt = np.zeros_like(state)
    dydt[0] = state[1]
    dydt[1] = -(G/L)*np.sin(state[0])
    return dydt

#設定
t_span = [0,20] #時間 (s)
dt = 0.05# 時間の間隔 (s)
t = np.arange(t_span[0], t_span[-1], dt)# 時間の間隔のarray作成

#初期状態設定
th1 = 45.0# 角度 [deg]
w1 = 0.0 # 初期角速度 [deg/s]
state = np.radians([th1, w1])# 初期状態

#微分方程式を解く
sol = solve_ivp(eom, t_span, state, t_eval=t)
theta = sol.y[0] #y[0]=θ、y[1]=ω

x = L * np.sin(theta)       
y = -L * np.cos(theta)      

#ーーーーーーグラフーーーーーーー
fig, ax = plt.subplots()

line, = ax.plot([], [], "o-", linewidth=2) 
locus, = ax.plot([], [], 'r-', linewidth=2)
xlocus, ylocus = [], []
time_template = "time = %.1fs"
time_text = ax.text(0.05, 0.9, " ", transform=ax.transAxes)


def init():
    line.set_data([], [])
    time_text.set_text("")
    return line, time_text

def animate(i):
    thisx = [0, x[i]]
    thisy = [0, y[i]]
    line.set_data(thisx, thisy)
    xlocus.append(x[i])
    ylocus.append(y[i])

    locus.set_data(xlocus, ylocus)
    time_text.set_text(time_template % (i*dt))
    return line,xlocus, ylocus, time_text


ani = FuncAnimation(fig, animate, frames=np.arange(0, len(t))
                    , interval=25, blit=True,init_func=init)

ax.set_xlim(-L-0.5,L+0.5)
ax.set_ylim(-L-0.5,L+0.5)
ax.set_aspect("equal")
ax.grid()

plt.show()

#ani.save("XXX.gif", writer="pillow", fps=20)

 

youtu.be

 

複数の単振り子

次に複数の単振り子です。

 

%matplotlib nbagg
G = 9.8  # 重力加速度(m/s^2)
L = 1.0  # 振り子の長さ(m)

# 運動方程式を解く
def eom(t, state):
    dydt = np.zeros_like(state)
    dydt[0] = state[1]
    dydt[1] = -(G/L)*np.sin(state[0])
    return dydt

#設定
t_span = [0,20] #時間 (s)
dt = 0.05# 時間の間隔 (s)
t = np.arange(t_span[0], t_span[-1], dt)# 時間の間隔のarray作成

#初期状態設定

th1s = np.arange(40.0,90.0,10.0)
w1 = 0.0 # 初期角速度 [deg/s]

states=[]
for th1 in th1s:
    state = np.radians([th1, w1])# 初期状態
    states.append(state)

thetas=[]
for state in states:
    sol = solve_ivp(eom, t_span, state, t_eval=t)
    theta = sol.y[0] #y[0]=θ、y[1]=ω
    thetas.append(theta)

xs,ys=[],[]
for theta in thetas:
    x = L * np.sin(theta)  
    y = -L * np.cos(theta)  
    xs.append(x)
    ys.append(y)
    
    
#ーーーーーーグラフーーーーーーー
fig, ax = plt.subplots()

lines=[]
for i in range(len(th1s)):
    line, = ax.plot([], [], 'o-', lw=2, label=th1s[i])
    lines.append(line,)

time_template = "time = %.1fs"
time_text = ax.text(0.05, 0.9, " ", transform=ax.transAxes)


def init():
    for line in lines:
        line.set_data([], [])
    time_text.set_text("")
    return line, time_text

def animate(i):
    for j in range(len(lines)):
        line = lines[j]
        thisx = [0, xs[j][i]]
        thisy = [0, ys[j][i]]
        line.set_data(thisx, thisy)

    time_text.set_text(time_template % (i*dt))
    return line, time_text


ani = FuncAnimation(fig, animate, frames=np.arange(0, len(t))
                    , interval=25, blit=True,init_func=init)

ax.set_xlim(-L-0.5,L+0.5)
ax.set_ylim(-L-0.5,L+0.5)
ax.legend(title="init $\\theta$")
ax.set_aspect("equal")
ax.grid()

plt.show()

3ani.save("XXX.gif", writer="pillow", fps=20)

 

youtu.be

 

 

次は二重振り子によるカオスをアニメーションで描写したいと思います!

 

それでは🌏

 

【Matplotlib】アニメーション(FuncAnimation)

こんにちは

今日はMatplotlibのFuncAnimationを使ってアニメーションを作成したいと思います。

 

 

 

 グラフ作成

Step1

まずはドキュメントの3個目のsin関数を描写してみましょう。

matplotlib.org

 

Step2

ドキュメントを参考にして

「y=ax²」のグラフを描いてみます。

モジュール
import numpy as np
import matplotlib.pyplot as plt
from matplotlib.animation import FuncAnimation

 

グラフ
%matplotlib nbagg
fig, ax = plt.subplots()
#y = ax^2
xdata, ydata = [], []
line, = plt.plot([], [], "b-") #*1
a = 1/2

def init():
    ax.set_title("Basic")
    
    ax.set_xlim(-10,10)
    ax.set_ylim(-100,100)
#*2 ax.axhline(y=0, xmin=-10, xmax=10, color="k", linestyle="--") ax.axvline(x=0, ymin=-100, ymax=100, color="k", linestyle="--") ax.set_xlabel("X") ax.set_ylabel("Y") ax.grid() #*3 return line, def update(frame): #y=ax^2 xdata.append(frame) ydata.append(a*(frame)*(frame)) line.set_data(xdata, ydata) return line, ani = FuncAnimation(fig, update, frames=np.linspace(-10, 10, 40), init_func=init, blit=True) #*4 plt.show() #ani.save("XXX.gif", writer="pillow", fps=15)

 

f:id:RuntaScience:20200621114335g:plain

Keys

1) "b-"⇒colorが「b(blue)」でlineが「-」です

2) axhline(y=Y, xmin=最小値, xmax=最大値)⇒y=Yで直線を引く

 axvline(x=X, ymin=最小値, ymax=最大値)⇒x=Xで直線を引く

3) 図にグリッド欄を拭く

4) np.linspace(a, b, n)⇒初項a、末項bで、項数nの等差数列を作成

(e.g.)

np.linspace(0,20,20)
⇒array([ 0. , 1.05263158, 2.10526316, 3.15789474, 4.21052632,
5.26315789, 6.31578947, 7.36842105, 8.42105263, 9.47368421,
10.52631579, 11.57894737, 12.63157895, 13.68421053, 14.73684211,
15.78947368, 16.84210526, 17.89473684, 18.94736842, 20. ])

 

 Step3

 最後に複数の線をプロットしてみます

 

モジュール
import numpy as np
import matplotlib.pyplot as plt
from matplotlib.animation import FuncAnimation

 

グラフ

 

%matplotlib nbagg

fig, ax = plt.subplots()
#sin
xdata, ydata = [], []
ln, = plt.plot([], [], "b-")
#cos
xdata2, ydata2 = [], []
ln2, = plt.plot([], [], "r-")
#tan
xdata3, ydata3 = [], []
ln3, = plt.plot([], [], "go",alpha=0.5)

def init():
    ax.set_title("SIN & COS & TAN")
    
    ax.set_xlim(-2*np.pi, 2*np.pi)
    ax.set_ylim(-1, 1)
    ax.axhline(y=0, xmin=-2*np.pi, xmax=2*np.pi, color="k", linestyle="--")
    ax.axvline(x=0, ymin=-1, ymax=1, color="k", linestyle="--")
    
    ax.set_xticks(np.arange(-2*np.pi,2*np.pi+0.01,(1/2)*np.pi)) #*2
    ax.set_xticklabels(["-2$\pi$","-3/2$\pi$","-$\pi$","-1/2$\pi$", "0","1/2$\pi$","$\pi$","3/2$\pi$", "2$\pi$"]) #*1, 2
    ax.set_xlabel("$\\theta$") #*2
    ax.grid()
    
    return ln,

def update(frame):
    #sin
    xdata.append(frame)
    ydata.append(np.sin(frame))
    ln.set_data(xdata, ydata)
    #cos
    xdata2.append(frame)
    ydata2.append(np.cos(frame))
    ln2.set_data(xdata2, ydata2)
    #tan
    xdata3.append(frame)
    ydata3.append(np.tan(frame))
    ln3.set_data(xdata3, ydata3)
    
    return ln,ln2,ln3

ani = FuncAnimation(fig, update, frames=np.linspace(-2*np.pi, 2*np.pi, 300),
                    init_func=init, blit=True)
plt.show()

# ani.save("XXX.gif", writer="pillow", fps=15)

 

f:id:RuntaScience:20200621114331g:plain

 

Keys

1)ラベルをラジアンに変換

2)ギリシャ文字 

runtascience.hatenablog.com

 

いかがだったでしょうか。

 

それでは🌏

 

【Matplotlib】2軸のグラフを作成しよう

こんにちは!2軸のグラフ作成をします

 

 データの用意ができていて、図の書き方だけ知りたいという方は、描写 2軸へ!!

 

 

モジュール

必要なモジュールをインポートします

import numpy as np
import matplotlib.pyplot as plt

 

データ

 それではまず初めにデータを用意します。

今回はランダムなデータを使用します。

x = np.arange(0,100,1)
y1 = np.random.rand(100)
y2 = np.random.rand(100) * 100

 

描写

1軸

2軸の描写の前に、それぞれのデータをプロットして確認しておきましょう。

 

fig = plt.figure(figsize=(10, 5))
plt.rcParams["font.size"] = 18 #fontsize一括設定
ax1 = plt.subplot(211)
ax2 = plt.subplot(212)

ax1.plot(x, y1)
ax2.plot(x, y2)

#軸設定
ax1.set_ylabel("Y1-axis")
ax2.set_ylabel("Y2-axis")
ax1.label_outer()

plt.show()
#保存
fig.savefig("XXX.png" ,format="png", dpi=330)

 f:id:RuntaScience:20200620211604p:plain

 

2軸

それでは本題の2軸グラフです。

今回の目的は2軸グラフの描写なので、細かい設定はしません。

fig = plt.figure(figsize=(10, 3))
plt.rcParams["font.size"] = 18
ax1 = plt.subplot(111)
ax2 = ax1.twinx() #*1

ax1.plot(x, y1, color="b", label = "Y1")
ax2.plot(x, y2, color="r", label = "Y2")

#軸設定
ax1.set_ylabel("Y1-axis")
ax2.set_ylabel("Y2-axis")
#範囲設定
ax1.set_xlim(0,100)
ax1.set_ylim(0,1.2)
ax2.set_ylim(0,120)

#*2 h1, l1 = ax1.get_legend_handles_labels() h2, l2 = ax2.get_legend_handles_labels() ax1.legend(h1+h2, l1+l2, ncol=2, fontsize=12) plt.show() fig.savefig("XXX.png" ,format="png", dpi=330)

 

f:id:RuntaScience:20200620211549p:plain

 Keys

1) ax2は、ax1に.twinx()で結合します

2)凡例(legend)の表示です。

通常に

ax1.legend()
ax2.legend()

としても良いのですが、それぞれが独立してしまうため表示が不自然になります。

したがって、.get_legend_handles_labels()から得られたhとlを足し算することによって統一の凡例が表示できます。

参考

matplotlib.org

 

ちなみにbarで違うデータを表示させると以下のようになります。

このようにすると、2つのデータの対比がしやすくなりますね!

 

f:id:RuntaScience:20200620211518p:plain

 

 

それでは 🌏

【Science】水平線までどのくらいの距離?Part2ーマップで表示

こんにちは!
前回に引き続き、Cartopyでマップに表示したいと思います

[前回の記事]

水平線までどのくらいの距離なのか?

 

 

runtascience.hatenablog.com

 

 

 

今回はCartopyを使ってどこまで見られるのか表示してみました!

都道府県などの境を表示するためにGADMシェープファイルを利用させていただきました。

[ シェープファイル利用(Japan⇒Shapefile)]

gadm.org

地図

大気スケール

 まずは大気スケールです。

日本列島の端から端まではだいたい2000 kmです

したがって、半径が1000 kmだとだいたい日本列島全体が見れますね

飛行機の高度の10 kmくらいの時はいちばん小さい円です。

それでも関東地方全体は軽く眺められますね。

f:id:RuntaScience:20200620103556p:plain

 

スケール H D
名前 m km
大気 熱圏 10000 1133.23
中間層 8000 1012.8
成層圏 5000 799.75
対流圏 1000 357.099

山スケール

次に山スケールです。

今回は富士山とエベレストのみにします。(他はそこまで高さが変わらないので)

赤の点は富士山頂です。

富士山とエベレストで見られる範囲を比べると100 km程しか変わらないのでそこまで違いが見られませんね。それにしても、山に登るだけでここまで見れるのはすごいですよね。

f:id:RuntaScience:20200620103549p:plain

 

建物スケール

次に建物スケールです。

赤い点は東京スカイツリーです。(634 m)

世界1位のブルジュハリファとスカイツリーを比較してもあまり見える距離は変わらないんですね。意外です。

しかし、東京タワーと比べると差が大きくなりますね。

都内の大きな高層マンションでは水平距離で24区見れそうですね、障害物がなければですが(笑

f:id:RuntaScience:20200620103539p:plain

 

スケール H D
名前 m km
建物 ブルジュ ハリファ 828 102.7
東京スカイツリー 634 89.9
東京タワー  333 65.1
福岡タワー 234 54.6
40階 150 43.7
20階 60 27.7
10階 30 19.6
5階 12 12.4
3階 9 10.7
2階 6 8.7

 

人スケール

最後に人スケールです。

平均身長あたりだと150ー170 cmなので見られる距離は4キロほどです。

東京ディズニーリゾートのある舞浜からです。

実際東京湾に立つと、羽田空港から千葉県が見られますし、千葉県から東京や川崎が見られます。

それは、水平線ではなく建物の高さがあるためや地上の高低差ならびに大気の屈折があるためと考えられます。

f:id:RuntaScience:20200620103532p:plain

スケール H D
名前 m km
身長 10cm 0.1 1.1
30cm 0.3 2
50cm 0.5 2.5
70cm 0.7 3
90cm 0.9 3.4
110cm 1.1 0.7
130cm 1.3 4.1
150cm 1.5 4.4
170cm 1.7 4.7
190cm 1.9 4.9
210cm 2.1 5.2
230cm 2.3 5.4
250cm 2.5 5.6
270cm 2.7 5.9

 

 コード

まずは描写に必要なモジュールをインポートします

 

import matplotlib.pyplot as plt       
import cartopy.crs as ccrs               
import cartopy.feature as cfeature 
#shape file
import cartopy.io.shapereader as shpreader

 

 次に、地球状のどこかかの点から円を描くので

半径(r km)と中心の緯度経度から、円の緯度経度座標に変換します

# 円
def circle(r,S,T):
    #r:radius(km), (S,T):centerDegree
    s,t = S*111, T*111
    points = 1000  
    theta = np.linspace(0, 2 * np.pi, points)
    x = r * np.sin(theta) + s
    y = r * np.cos(theta) + t
    
    #x,y=>Degree
    X, Y = x/111, y/111
    return (X,Y)

 Keys

「km⇄緯度経度」は赤道半径を利用した値で変換しました

km = Degree ✕ 111

 

それでは描写してみます

def main():
    fig = plt.figure(figsize=(5,5))
    plt.rcParams["font.size"] = 18
    # TokyoStation
    ts_lon = 139.767125
    ts_lat = 35.681236
    
    ax = fig.add_subplot(1,1,1, projection=ccrs.PlateCarree())
    ax.set_extent([ts_lon-1, ts_lon+1, ts_lat-1, ts_lat+1], crs=ccrs.PlateCarree())
    ax.set_title("Title")

    ax.add_feature(cfeature.BORDERS, linestyle=":")
    #都道府県境と市町村境
    fname1 = "data/gadm36_JPN_shp/gadm36_JPN_1.shp" 
    fname2 = "data/gadm36_JPN_shp/gadm36_JPN_2.shp"
    adm1_shapes = list(shpreader.Reader(fname1).geometries())
    adm2_shapes = list(shpreader.Reader(fname2).geometries())
    
    #データのプロット
    ax.add_geometries(adm1_shapes, ccrs.PlateCarree(),
                  edgecolor="k",facecolor="w",alpha=0.5) 
    ax.add_geometries(adm2_shapes, ccrs.PlateCarree(),
                  edgecolor="gray", facecolor="w",  alpha=0.5) 
    
    #TokyoStation
    
    ax.scatter(ts_lon,ts_lat,s=20,c="r",alpha=1, zorder=10)
    c = circle(100, ts_lon,ts_lat)
    ax.plot(c[0],c[1],c="b",alpha=1, zorder=10)
    
    plt.show()

if __name__ == "__main__":
    main()

 

参考コード

qiita.com

 

geopandas.readthedocs.io

 

それでは🌏

 

 

関連記事

 

runtascience.hatenablog.com

 

 

runtascience.hatenablog.com

 

【Science】水平線までどのくらいの距離?Part1

こんにちは!

 

皆さん水平線までの距離ってどのくらいなんだろうって考えたことありませんか?

今回はそれを計算してみました。

www.livescience.com

 

 

 

計算

 半径をrとし、地表面からの高さをhとします。

f:id:RuntaScience:20200620103525p:plain

そして地球(あるいは天体)を完全な球体と仮定し、hと円との接線を引き、そこまでの距離をdとします。三平方の定理より、

d 2 + r 2 =h + r2

d =h(2r + h)

∵d>0

※簡易的な計算であるため、dまでには障害物がないと仮定し、大気による光の屈折はしないと仮定します。地域で気温や大気質に違いがあるため、考慮しないです。

※実際見える対象物は平面ではなく、高さがあるのでdまでが見える範囲とは限りません。

 

高さと距離の関係

試しにエベレストで距離dを調べてみました。エベレストの標高は8848 mですので、

地球の赤道半径6378 kmを利用すると、約340 kmでした。

意外と見れますね。

これを踏まえていろいろな高さから見られる距離を求めてみました。

f:id:RuntaScience:20200620103512p:plain

グラフ

大気スケール

上から熱圏中間層成層圏対流圏です。

高度が高くなればなるほど見える距離は大きくなりますが、その変化の幅は小さくなります。

それはdの式がh²のルートに比例するからでしょう。

f:id:RuntaScience:20200620103459p:plain

山スケール

世界の山ランキングと日本の山ランキングからのデータをプロットしました。

世界トップ10の山はどれも8000 m級で、それほど差が無いので見える距離もほどんど変わらず、300ー350 km

日本のトップテンも同様に3000 m急なので、200 km

という結果になりました。

 

f:id:RuntaScience:20200620103628p:plain

Highest Mountain Peaks of the World

標高の高い山−標高ベスト100 登山と山の話題

 

建物スケール

次はさらに低い建物で見ていきます。

世界一のブルジュハリファだと102 m

日本一の東京スカイツリーだと90 m

でした。

他にも1階あたりを3 mとして、40 m, 20 m, 10m, 5m, 3m, 2mと計算してみましたf:id:RuntaScience:20200620103616p:plain

人スケール

そして、身長によってどのくらい見える距離が変わるのかを調べてみました。

身長170 cmのとき4.7 km

身長150 cmのとき4.4 km

身長が20 cm違っても300 m位しか差がありませんね(笑

 

f:id:RuntaScience:20200620103603p:plain

 

太陽系

 先ほどまでは地球の半径で計算してきましたが、次に太陽系の惑星の半径で計算してみました。

高さは人スケールにしました。

太陽水星金星地球火星木星土星天王星海王星冥王星エリス

 

太陽は圧倒的に半径が大きいので差が明瞭に見られますね。

 

f:id:RuntaScience:20200620115458p:plain

 

まとめ 

人はだいたい4キロくらいですね

スケール H D スケール H D
名前 m km 名前 m km
大気 熱圏 10000 1133.23 建物 ブルジュ ハリファ 828 102.7
中間層 8000 1012.8 東京スカイツリー 634 89.9
成層圏 5000 799.75 東京タワー  333 65.1
対流圏 1000 357.099 福岡タワー 234 54.6
山(世界) エベレスト 8850 335.9 40階 150 43.7
K2 8611 331.4 20階 60 27.7
カンチェンジュンガ  8586 330.9 10階 30 19.6
ローツェ 8516 329.5 5階 12 12.4
マカルー 8463 328.5 3階 9 10.7
チョ・オユ- 8201 323.4 2階 6 8.7
ダウラギリ 8167 322.7 身長 10cm 0.1 1.1
マナスル 8163 322.6 30cm 0.3 2
ナンガ・パルバット 8125 321.9 50cm 0.5 2.5
アンナプルナ 8091 321.2 70cm 0.7 3
山(日本) 富士山 3776 219.4 90cm 0.9 3.4
北岳 3193 201.7 110cm 1.1 0.7
奥穂高岳 3190 201.6 130cm 1.3 4.1
間ノ岳 3190 201.6 150cm 1.5 4.4
槍ヶ岳 3189 201.3 170cm 1.7 4.7
東岳 3141 200.1 190cm 1.9 4.9
赤石岳 3121 199.4 210cm 2.1 5.2
涸沢岳 3110 199.1 230cm 2.3 5.4
北穂高岳 3106 199 250cm 2.5 5.6
大喰岳 3101 198.8 270cm 2.7 5.9

 

 是非皆さんも半径や高度を変えていろいろと調べてみてください!

 

それでは🌏

 

 

 

【Jupyter Notebook】記号

こんにちは!

 

科学(気象系)で主に使う記号を紹介します。

LaTeXと少し違って、「\」を2つ付けるものもあるので注意しましょう。

 

  Symbol_1   Symbol_2
Symbol Name Letter Jupyter Symbol Name Letter Jupyter
イコール = = 大なり > >
ノットイコール $\\neq$ 小なり < <
ニアリーイコール $\simeq$ 十分大 $\gg$
プラス + 十分小 $\ll$
マイナス $-$ 以上 $\geq$
掛ける × $\\times$ 以上 $\geqq$
割る ÷ $\div$ 以下 $\leq$
プラスマイナス ± $\pm$ 以下 $\leqq$
マイナスプラス $\mp$ 無限 $\infty$

f:id:RuntaScience:20200618154349p:plain

Keys

neq = not equal

simeq = similar equal

div = division

pm = plus minus

mp = minus plus

geq = greater or equal

leq = less or equal

infty = infinity

 

 

参考(LaTeX)

medemanabu.net

 

 

それでは🌏

 

類似記事

 

runtascience.hatenablog.com

【Jupyter Notebook】ギリシャ文字

 こんにちは

今回は、Jupyternotebookでグラフ作成時によく使う

ギリシャ文字についてです。

 

小文字のαやβなどの文字は、「\」を二つ(「\\」)付けないといけないので

注意しましょう。

 

 

  Capital Small
Greek Alphabet Letter Jupyter Letter Jupyter
アルファ Α $A$ α $\\alpha$
ベータ B $B$ β $\\beta$
ガンマ Γ $\Gamma$ γ $\gamma$
デルタ Δ $\Delta$ δ $\delta$
イプシロン Ε $E$ ε $\epsilon$
ゼータ Z $Z$ ζ $\zeta$
エータ Η $H$ η $\eta$
シータ Θ $\\Theta$ θ $\\theta$
イオタ Ι $I$ ι $\iota$
カッパ Κ $K$ κ $\kappa$
ラムダ Λ $\Lambda$ λ $\lambda$
ミュー M $M$ μ $\mu$
ニュー N $N$ ν $\\nu$
クサイ Ξ $\\Xi$ ξ $\\xi$
オミクロン Ο $O$ ο $\o$
パイ Π $\Pi$ π $\pi$
ロー Ρ $P$ ρ $\\rho$
シグマ Σ $\Sigma$ σ $\sigma$
タウ Τ $T$ τ $\\tau$
ウプシロン Υ $\\Upsilon$ υ $\\upsilon$
ファイ Φ $\Phi$ φ $\phi$
キー Χ $X$ χ $\chi$
プサイ Ψ $\Psi$ ψ $\psi$
オメガ Ω $\Omega$ ω $\omega$

 

f:id:RuntaScience:20200617171816p:plain

 参考

medemanabu.net

 

それでは🌏

 

類似記事

 

runtascience.hatenablog.com

 

【Matplotlib】Gridspecーグラフの柔軟な分割(3:1でもで4:1でも)

こんにちは。

 

グラフの分割をすると思うのですが、普通に分割すると1:1とか一つ一つが同じ大きさのグラフになりますよね。

そこで今回はMatplotlibのGridspecを用いて、3:1やさらに複雑なグラフの分割をしていきたいと思います!

 

★事前に必要な知識

グラフの基本的な書き方(matplotlib)

リストのスライス

 

 

 

基礎

まずは今回使うGridspecをインポートしましょう・

 

import matplotlib.pyplot as plt
from matplotlib import gridspec

 

 

例1

 縦方向に3:1で分割してみます

 

fig = plt.figure(figsize=(4,3))
#分割 *1 ncols=2 nrows=1 gs = gridspec.GridSpec(ncols, nrows, height_ratios=(3, 1)) ax1 = fig.add_subplot(gs[:1, 0]) ax2 = fig.add_subplot(gs[-1, 0]) ax1.text(0.5,0.5, "ax1", fontsize=30, horizontalalignment='center', verticalalignment='center',) ax2.text(0.5,0.5, "ax2", fontsize=30, horizontalalignment='center', verticalalignment='center',) #グラフ間の隙間 plt.subplots_adjust(hspace=0.25) fig.savefig("XXX.png", format='png', dpi=330)

f:id:RuntaScience:20200616162419p:plain

Key
 1) gridspec.GridSpec(縦方向分割数, 横方向分割数, height_ratios=(3, 1))

 height_ratioはその比率です。

 

例2

 横方向に1:3で分割してみます

 

fig = plt.figure(figsize=(4,3))
ncols=1
nrows=2
gs = gridspec.GridSpec(ncols, nrows, width_ratios=(1,3)) #*1
ax1 =  fig.add_subplot(gs[0, 0])
ax2 =  fig.add_subplot(gs[0, 1:])

ax1.text(0.5,0.5, "ax1", fontsize=30,
        horizontalalignment='center',
        verticalalignment='center',)
ax2.text(0.5,0.5, "ax2", fontsize=30,
        horizontalalignment='center',
        verticalalignment='center',)

#グラフ間の隙間
plt.subplots_adjust(wspace=0.25)

fig.savefig("XXX.png", format='png', dpi=330)

 

 

f:id:RuntaScience:20200616162414p:plain

Key
 1) gridspec.GridSpec(縦方向分割数, 横方向分割数, width_ratios=(1, 3))

 width_ratioはその比率です。

 

応用

さらに柔軟にグラフを描いてみましょう

例3

 縦方向に1:3で、横方向に3:1に分割してみましょう

 

fig = plt.figure(figsize=(6, 6))
ncols=2
nrows=2
gs = gridspec.GridSpec(ncols, nrows, height_ratios=(1, 3), width_ratios=(3, 1))
ax1 =  fig.add_subplot(gs[:1, :1])
ax2 =  fig.add_subplot(gs[-1, :1])
ax3 =  fig.add_subplot(gs[:1, -1])
ax4 =  fig.add_subplot(gs[-1, -1])

ax1.text(0.5,0.5, "ax1", fontsize=30,
        horizontalalignment='center',
        verticalalignment='center',)
ax2.text(0.5,0.5, "ax2", fontsize=30,
        horizontalalignment='center',
        verticalalignment='center',)
ax3.text(0.5,0.5, "ax3", fontsize=30,
        horizontalalignment='center',
        verticalalignment='center',)
ax4.text(0.5,0.5, "ax4", fontsize=30,
        horizontalalignment='center',
        verticalalignment='center',)

#グラフ間の隙間
plt.subplots_adjust(hspace = 0.20, wspace=0.25)

fig.savefig("XXX.png", format='png', dpi=330)

 

 

f:id:RuntaScience:20200616162436p:plain

 

例4

 次は比をばらばらにして分割してみましょう

 

fig = plt.figure(figsize=(6, 6))
ncols=3
nrows=2
gs = gridspec.GridSpec(ncols, nrows, height_ratios=(1, 1, 1), width_ratios=(3, 1))
ax1 =  fig.add_subplot(gs[:2, :1])
ax2 =  fig.add_subplot(gs[-1, :1])
ax3 =  fig.add_subplot(gs[:1, -1])
ax4 =  fig.add_subplot(gs[1:, -1])

ax1.text(0.5,0.5, "ax1", fontsize=30,
        horizontalalignment='center',
        verticalalignment='center',)
ax2.text(0.5,0.5, "ax2", fontsize=30,
        horizontalalignment='center',
        verticalalignment='center',)
ax3.text(0.5,0.5, "ax3", fontsize=30,
        horizontalalignment='center',
        verticalalignment='center',)
ax4.text(0.5,0.5, "ax4", fontsize=30,
        horizontalalignment='center',
        verticalalignment='center',)

#グラフ間の隙間
plt.subplots_adjust(hspace = 0.3,wspace=0.25)

fig.savefig("XXX.png", format='png', dpi=330)

 

 

f:id:RuntaScience:20200616162424p:plain

 

例5

 さらに細かく変形してみましょう

fig = plt.figure(figsize=(6, 6))
ncols=3
nrows=3
gs = gridspec.GridSpec(ncols, nrows, height_ratios=(1, 1, 1), width_ratios=(2, 2, 1))
ax1 =  fig.add_subplot(gs[:2, :2])
ax2 =  fig.add_subplot(gs[-1, :1])
ax3 =  fig.add_subplot(gs[-1, 1:2])
ax4 =  fig.add_subplot(gs[:1, -1])
ax5 =  fig.add_subplot(gs[1:, -1])

ax1.text(0.5,0.5, "ax1", fontsize=30,
        horizontalalignment='center',
        verticalalignment='center',)
ax2.text(0.5,0.5, "ax2", fontsize=30,
        horizontalalignment='center',
        verticalalignment='center',)
ax3.text(0.5,0.5, "ax3", fontsize=30,
        horizontalalignment='center',
        verticalalignment='center',)
ax4.text(0.5,0.5, "ax4", fontsize=30,
        horizontalalignment='center',
        verticalalignment='center',)
ax5.text(0.5,0.5, "ax5", fontsize=30,
        horizontalalignment='center',
        verticalalignment='center',)


#グラフ間の隙間
plt.subplots_adjust(hspace = 0.3, wspace=0.4)

fig.savefig("XXX.png", format='png', dpi=330)

 

f:id:RuntaScience:20200616162430p:plain

 いかがだったでしょうか。

Grodspecを用いると、柔軟にグラフを分割することが可能です。

是非試してみてください!

 

それでは🌏

プライバシーポリシー
お問い合わせ