NumPyの1変数多項式クラス

Pythonで多項式を扱う時はSympyを使うものだと思い込んでいたのですが、
NumPyにも多項式クラスが用意されいるのを見つけ、しかもかなり使い勝手が良かったので紹介します。

ドキュメント: numpy.poly1d

これを使えば簡単に多項式を生成し、多項式間の演算を行ったり値を代入したりすることができます。
まず、多項式の生成は次の2種類のやりかでできます。

– 高次の項から順番に係数を指定する。
– その多項式の根を指定する。(この場合、再高次の項の係数は1)。

$2x^3-4x^2-22x+24$ と $(z-1)(z+2)=z^2+z-2$ をそれぞれの方法で定義したのが次のコードです。


import numpy as np

# 係数を指定する場合は、高次の項から順番に指定する
p1 = np.poly1d([2, -4, -22, 24])
print(p1)
"""
   3     2
2 x - 4 x - 22 x + 24
"""

# r=True を指定することで、根を指定して生成できる
# variable で変数の文字も指定できる(デフォルトはx)
p2 = np.poly1d([-2, 1], r=True, variable="z")
print(p2)
"""
   2
1 z + 1 z - 2
"""

係数のリストはc、次数はo、根の一覧はr、という属性でそれぞれアクセスすることができます。
係数と根はその多項式オブジェクトを作る時に指定した方法に関係なく取得できて便利です。
方程式を解くのもこれでできますね。


# 係数のリスト
print(p1.c)
# [  2  -4 -22  24]

# 次数
print(p1.o)
# 3

# 根
print(p1.r)
# [-3.  4.  1.]

また、指定した次数の係数は辞書と同じように[次数]でアクセスできます。


# x^2 の係数
print(p1[2])
# -4

値の代入は通常の関数と同じように、 多項式オブジェクト(代入したい値) で計算できます。


# p1 に 2 を代入
print(p1(2))
# -20

このほか、 通常の +, -, * の 演算子で演算もできます。
/ は割り算ですが、商と余りを返してくれます。とても便利ですね。


p = np.poly1d([2, 7, 1, 4, 3])
q = np.poly1d([1, 3, 5])

print(p+q)
"""
   4     3     2
2 x + 7 x + 2 x + 7 x + 8
"""

print(p-q)
"""
   4     3     2
2 x + 7 x + 2 x + 7 x + 8
"""

print(p*q)
"""
   6      5      4      3      2
2 x + 13 x + 32 x + 42 x + 20 x + 29 x + 15
"""

print(p/q)
# (poly1d([  2.,   1., -12.]), poly1d([35., 63.]))

このほかさらに、polyderとpolyintで微分と不定積分も用意されています。


# 微分
print(np.polyder(p))
"""
   3      2
8 x + 21 x + 2 x + 4
"""

# 不定積分
print(np.polyint(p))
"""
     5        4          3     2
0.4 x + 1.75 x + 0.3333 x + 2 x + 3 x
"""

例は省略しますが、2個目の引数に自然数を渡せばn回微分や、n回積分もやってくれます。
積分の方は、3つ目の引数に積分定数を渡すこともできます。

数値をゼロ埋めして桁数を揃える

桁数の揃ったIDを振るときや、表の見栄えを整える時など、桁数が少ない数字の左側に0をくっつけて表示することがあります。
そうそう頻繁にあることではないので、これまでそういう操作が必要な時は、
単純に0をたくさんくっつけて規定文字数を右側から取り出す関数を作って対応していました。

例えば次のようなメソッドを定義していました。
例として 123 を 0埋めして6桁にしています。


def zero_padding(n, length):
    m = "0" * length + str(n)
    return m[-length:]


print(zero_padding(123, 6))
# 000123

普段の用途だとこれでもあまり困らないのですが、実はPythonにはゼロ埋め専用の関数が用意されていたのに気づいたのでそちらを紹介します。
文字列オブジェクトに定義されている、zfillメソッドがそれです。

ドキュメント: str.zfill(width)
str型が持ってるメソッドなので、数値型のデータに適用するにはstrに変換してから呼び出す必要があります。

このメソッドは上のコードで僕が定義した単純な関数に比べて次の2点で優れています。
– 数字がwidth桁未満の時は、元の数字をそのまま返す。(上の方の桁をロストしない)
– 文字列の先頭が+か-の符号の場合、符号を先頭としてその後ろを0埋めする。
対応する符号は+と-だけで、±はダメみたいでした。

挙動を確認するため、いくつかのパターンでやってみます。


# 123をゼロ埋めして7桁にする
print("123".zfill(7))
# 0000123

# 幅が元の数値の桁数未満なら元の数値をそのまま返す。
print("12345".zfill(3))
# 12345

# 先頭が符号の場合は符号と数字の間をゼロ埋めする。符号も結果の文字数にカウントされる。
print("-5678".zfill(8))
# -0005678

# 小数点も文字数に数えられる。
print("+12.34".zfill(6))
# +12.34

# 数字以外の文字列に対しても使える。
print("abc".zfill(5))
# 00abc

小数や負の数をゼロパディングする機会にはまだ遭遇したことないのですが、覚えておいて損はないと思います。

Matplotlibでヒストグラムを描く時に各binのレンジを明示的に指定する方法

そもそも、Tableauなどを使えばこんな手間もないのですが、Python(Matplotlib)でヒストグラムを描く時に、各ビンの区間を指定したいことがよくあります。
0かはじめて0.5区切りにしたいとか20区切りにしたいとかです。
Matplotlibのhistメソッドでは、bins引数で、binの引数を指定でき、range引数でヒストグラムに描写する幅を指定できるので、
僕はこれまではこの二つを組み合わせて使うことで、想定通りのヒストグラムを描いていました。

試しに、 0 〜 300のデータを 20区切りで、15本のbinでヒストグラムに表示するコードがこれです。
hist メソッドの戻り値で binの区切り位置が取れるので、そちらを確認し、出力の図は省略します。
参考: matplotlibのhist()の戻り値


import matplotlib.pyplot as plt
from scipy.stats import beta

# データ生成
beta_frozen = beta(a=1, b=1, scale=300)
data = beta_frozen.rvs(100)

fig = plt.figure(facecolor="w")
ax = fig.add_subplot(111)
ns, bins, _ = ax.hist(data, bins=15, range=(0, 300))
print(bins)
# [  0.  20.  40.  60.  80. 100. 120. 140. 160. 180. 200. 220. 240. 260. 280. 300.]

これ、もしreangeを指定せずに、bins=15だけ指定しているととても中途半端なところで区切られます。


fig = plt.figure(facecolor="w")
ax = fig.add_subplot(111)
ns, bins, _ = ax.hist(data, bins=15)
print(bins)
"""
[  0.59033775  20.53472376  40.47910977  60.42349579  80.3678818
 100.31226782 120.25665383 140.20103985 160.14542586 180.08981188
 200.03419789 219.9785839  239.92296992 259.86735593 279.81174195
 299.75612796]
"""

さて、上記のようなblog記事ように自分で生成したデータなど取りうるレンジがわかりきってるものであれば、上記のやり方でも問題なのですが、実データでは少しだけ面倒です。
レンジとデータ量を確認して、何本くらいのbinを指定すれば切りの良い区切りで可視化でできるか考えないといけません。

しかしドキュメントあたらめて読んでみると、bins引数で、ビンの本数ではなく、区間を配列で指定できることがわかりました。
参考: matplotlib.pyplot.hist

bins : int or sequence or str, optional

If an integer is given, bins + 1 bin edges are calculated and returned, consistent with numpy.histogram.
If bins is a sequence, gives bin edges, including left edge of first bin and right edge of last bin. In this case, bins is returned unmodified.

これを使うと、例えば20区切りで可視化したい、と言った時は次のような書き方ができます。


# 300を含めるため、2個目の引数は301にしました。
bins = range(0, 301, 20)
fig = plt.figure(facecolor="w")
ax = fig.add_subplot(111)
ns, bins, _ = ax.hist(data, bins=bins)
print(bins)
# [  0  20  40  60  80 100 120 140 160 180 200 220 240 260 280 300]

楽ですね。
注意点として、 bisで渡した配列の区間の外側のデータは可視化されないということがあります。
bins = range(0, 300, 20) とすると、binsの配列は、
[ 0 20 40 60 80 100 120 140 160 180 200 220 240 260 280]
になるので、 280~300のデータは可視化されません。
区間の下側も同様です。
なので、binsを指定する時に、データが全部その範囲に含まれているのかは確認しておく必要があります。

ちなみに豆知識ですが、各区間は最後(最大)の区間以外は、左の値を含み右の値を含みません、
[20, 40) の区間であれば、 $20 \leq x < 40$ のデータを数えます。
ただし、最後(最大)の区間に限って、右の値も含み、最大のbinが
[280, 300] の区間であれば、 $280 \leq x \leq 300$ のデータを数えます。

使いどこがすぐには思いつかないのですが、 bins を配列で指定する場合は、等間隔以外の区切りもサポートされているということも覚えておきましょう。

Scipyで対数正規分布

対数正規分布の話の続きです。
参考: 前回の記事

Pythonで対数正規分布を扱う場合、(もちろんスクラッチで書いてもいいのですが普通は)Scipyに実装されている、
scipy.stats.lognormを使います。
これに少し癖があり、最初は少してこずりました。

まず、対数正規分布の確率密度関数はパラメーターを二つ持ちます。
次の式の$\mu$と$\sigma$です。
$$
f(x) =\frac{1}{\sqrt{2\pi}\sigma x}\exp\left(-\frac{(\log{x}-\mu)^2}{2\sigma^2}\right).
$$

それに対して、scipy.stats.lognorm の確率密度関数(pdf)は、
s, loc, scale という3つのパラメーターを持ちます。 ややこしいですね。

正規分布(scipy.stats.norm)の場合は、 loc が $\mu$に対応し、scaleが$\sigma$に対応するので、とてもわかりやすいのですが、lognormはそうはなっていなっておらず、わかりにくくなっています。
(とはいえ、ドキュメントには正確に書いてあります。)

Scipyの対数正規分布においては、確率密度関数は
$$
f(x, s) = \frac{1}{sx\sqrt{2\pi}}\exp\left(-\frac{\log^2{x}}{2s^2}\right)
$$
と定義されています。
そして、$y=(x-loc)/scale$と変換したとき、lognorm.pdf(x, s, loc, scale) は、 lognorm.pdf(y, s) / scale と等しくなります。(とドキュメントに書いてあります。)
わかりにくいですね。

$\mu$と$\sigma$とはどのように対応しているのか気になるのですが、上の2式を見比べてわかるとおり、(そしてドキュメントにも書いてある通り、)
まず、引数のsが、パラメーターの$\sigma$に対応します。 (scaleじゃないんだ。)
そして、引数のscaleは$e^{\mu}$になります。(正規分布の流れで、locと$\mu$が関係してると予想していたのでこれも意外です。)
逆にいうと、$\mu=\log{scale}$です。

locはまだ登場していませんが、一旦ここまでの内容をプログラムで確認しておきます。
lognorm(s=0.5, scale=100) とすると、 $\sigma=0.5$で、$\mu=\log{100}\fallingdotseq 4.605$の対数正規分布になります。
乱数をたくさん取って、その対数が、期待値$4.605…$、標準偏差$0.5$の正規分布に従っていそうかどうかみてみます。


from scipy.stats import lognorm
import matplotlib.pyplot as plt
import numpy as np

data = lognorm(s=0.5, scale=100).rvs(size=10000)
log_data = np.log(data)
print("対数の平均:", log_data.mean())
# 対数の平均: 4.607122120944554
print("対数の標準偏差:", log_data.std())
# 対数の標準偏差: 0.49570170767616645

fig = plt.figure(figsize=(12, 6), facecolor="w")
ax = fig.add_subplot(1, 2, 1, title="元のデータ")
ax.hist(data, bins=100, density=True)
ax = fig.add_subplot(1, 2, 2, title="対数")
ax.hist(log_data, bins=100, density=True)
# 期待値のところに縦線引く
ax.vlines(np.log(100), 0, 0.8)

plt.show()

出力された図がこちらです。

想定通り動いてくれていますね。

残る loc ですが、 これは分布の値を左右に平行移動させるものになります。
先出の$y=(x-loc)/scale$ を $x = y*scale + loc$ と変形するとわかりやすいかもしれません、

わかりやすくするために、locに極端な値($\pm 1000$と$0$)を設定して、乱数をとってみました。
(sとscaleは先ほどと同じです。)


locs = [-1000, 0, 1000]

fig = plt.figure(figsize=(18, 6), facecolor="w")
for i, loc in enumerate(locs, start=1):
    data = lognorm(s=0.5, scale=100, loc=loc).rvs(size=1000)
    ax = fig.add_subplot(1, 3, i, title=f"loc={loc}")
    ax.hist(data, bins=100, density=True)

plt.show()

出力がこちらです。

分布の左端が それぞれ、locで指定した、 -1000, 0, 1000 付近になっているのがみて取れると思います。

対数正規分布

最近とあるデータのモデリングのために対数正規分布を使うことがありました。
そのとき使ったScipyのlognormには少し癖があったのでそれを紹介しようと思ったのですが、その前に対数正規分布そのものについて紹介させてもらいます。

対数正規分布とは一言で言ってしまうと、「それに従う確率変数の対数を取ったら正規分布に従うような確率分布」です。
正規分布の対数ではなく、対数を取ったら正規分布なので、注意が必要です。

もう少し正確に書きます。
確率変数$Y$が、正規分布$N(\mu, \sigma^2)$に従うとします。
このとき、$X=e^{Y}$は対数正規分布に従います。

定義に従って確率密度関数$f(x)$を導出しておきましょう。
まず、正規分布 $N(\mu, \sigma^2)$ の確率密度間数$g(y)$は、
$$
g(y) = \frac{1}{\sqrt{2\pi}\sigma}\exp\left(-\frac{(y-\mu)^2}{2\sigma^2}\right)
$$
です。
あとは$y=\log{x}$と$\frac{dy}{dx}=\frac{1}{x}$ に気をつけて、次のように計算できます。

$$
\begin{align}
f(x) &= g(y)\frac{dy}{dx}\\
&=g(\log{x})\frac{1}{x}\\
\therefore f(x) &=\frac{1}{\sqrt{2\pi}\sigma x}\exp\left(-\frac{(\log{x}-\mu)^2}{2\sigma^2}\right).
\end{align}
$$

ここで、$x$の値域は、 $0 <x < \infty$ です。
$\mu$ と $\sigma$ はパラメーターになります。
この導出の過程から明らかですが、それぞれ、対数正規分布に従う確率変数の「対数の」期待値と標準偏差です。
この二つがそのまま対数正規分布の期待値や標準偏差になるわけではないので気をつける必要があります。

対数ではない、確率変数$X$自体の期待値と分散は次の値になります。
参考: 対数正規分布 – Wikipedia
$$
\begin{align}
E[X] &= e^{\mu+\sigma^2/2}\\
V[X] &= e^{2\mu+\sigma^2}(e^{\sigma^2}-1)
\end{align}
$$

EC2の不要なインスタンスの消し方

とても単純な話なのですがかなり迷ったので備忘録的に残しておきます。

「インスタンスの削除」的なメニューがあるもんだと思ってずっと探していましたが、
実際には 「インスタンスの終了」 がそれにあたります。 (削除という文言がないのでなかなか気づきませんでした。)

消したいインスタンスを右クリックし、「インスタンスの状態」 => 「インスタンスの終了」 と選択することで消せます。
消してもしばらくはコンソール上に残るようです。

「終了保護」が設定されていると、終了ができないので、本当に消したい場合は事前に外しておきましょう。

pandasのDataFrameの欠損値をfillnaで埋める時の小技

DataFrameの欠損値(NoneやNaN)を定数で埋める時、fillnaというメソッドをよく使っていましたが、
定数で埋める以外にもいろいろ指定ができることがわかったので紹介します。

ドキュメントはこちらです。
pandas.DataFrame.fillna — pandas 1.1.2 documentation

まず、サンプルとして欠損値を含むDataFrameを作っておきます。


import pandas as pd
import numpy as np
df = pd.DataFrame(
    [[np.nan, 2, np.nan, 0],
     [3, 4, np.nan, 1],
     [np.nan, np.nan, np.nan, 5],
     [np.nan, 3, np.nan, 4]],
    columns=list('ABCD')
)
print(df)
"""
     A    B   C  D
0  NaN  2.0 NaN  0
1  3.0  4.0 NaN  1
2  NaN  NaN NaN  5
3  NaN  3.0 NaN  4
"""

fillnaの一番基本的な使い方は定数を指定するものです。
例えば、0を渡せばNaNを0に置き換えたDataFrameを返します。(inplace=True も指定すれば、データフレームそのものを書き換えます)


print(df.fillna(0))
"""
     A    B    C  D
0  0.0  2.0  0.0  0
1  3.0  4.0  0.0  1
2  0.0  0.0  0.0  5
3  0.0  3.0  0.0  4
"""

いつもはこうやって、数値なら0、文字列なら空文字列(“”)で埋めるだけの使い方をしていました。

しかし、ドキュメントを読むと、定数で埋める以外にもいろいろできます。

まず、定数ではなく、 列名: 値 の辞書を渡すことで、列ごとに別々の値で埋めることができます。


fill_values = {'A': 0, 'B': 1, 'C': 2, 'D': 3}
print(df.fillna(value=fill_values))
"""
     A    B    C  D
0  0.0  2.0  2.0  0
1  3.0  4.0  2.0  1
2  0.0  1.0  2.0  5
3  0.0  3.0  2.0  4
"""

そしてこれは、辞書の代わりに、indexに列名、valueに値を持つSeriesを渡しても同じ挙動になります。


fill_values_sr = pd.Series(fill_values)
print(fill_values_sr)
"""
A    0
B    1
C    2
D    3
dtype: int64
"""

print(df.fillna(value=fill_values_sr))
"""
     A    B    C  D
0  0.0  2.0  2.0  0
1  3.0  4.0  2.0  1
2  0.0  1.0  2.0  5
3  0.0  3.0  2.0  4
"""

これを応用すると、各列をその列の平均値や最大値、最小値で埋めることも簡単にできます。
平均値でやってみたコードが次です。


print(df.fillna(value=df.mean()))
"""
     A    B   C  D
0  3.0  2.0 NaN  0
1  3.0  4.0 NaN  1
2  3.0  3.0 NaN  5
3  3.0  3.0 NaN  4
"""

さて、ここまでは列単位である一定の値で欠損値を補完する方法でしたが、時系列データなどを扱っている時は、
一定の値ではなく、直前や直後の値で埋めたいこともあると思います。

実はこの fillna はそのようなケースにも対応しており、
method という引数に “backfill”か”bfill”を指定すれば直後の値、
“pad”, “ffill”を指定すれば直前の値で埋めることができます。

bfillとffillだけですがそれぞれ試してみたのが次のコードです。


print(df.fillna(method="bfill"))
"""
     A    B   C  D
0  3.0  2.0 NaN  0
1  3.0  4.0 NaN  1
2  NaN  3.0 NaN  5
3  NaN  3.0 NaN  4
"""

print(df.fillna(method="ffill"))
"""
     A    B   C  D
0  NaN  2.0 NaN  0
1  3.0  4.0 NaN  1
2  3.0  4.0 NaN  5
3  3.0  3.0 NaN  4
"""

以上のように、fillnaを使うと定数での補完(0埋めなど)以外にもいろんなことができることがわかりました。

pandasのデータフレームのexplodeメソッドの紹介

以前の記事で、pandasのDataFrameの列中に含まれている配列を行に展開する方法について書きました。
参考: pandasのDataFrameのappendは遅い

お恥ずかしながらこの記事を書いた時は知らなかったのですが、pandasの version 0.25.0 から、専用のメソッドが準備されていて、
先述の記事のような面倒なことはしなくて良くなっています。

そのメソッドが pandas.DataFrame.explode です。

使い方は簡単で、行に展開したい、つまり配列を含んだ列の名前を渡すだけです。

実際にやってみます。


import pandas as pd

df = pd.DataFrame(
    {'A': [[1, 2, 3], 'foo', [], [3, 4]], 'B': 1, "C": [1, 2, 3, 4]})
print(df)
"""
           A  B  C
0  [1, 2, 3]  1  1
1        foo  1  2
2         []  1  3
3     [3, 4]  1  4
"""

df_explode = df.explode('A')
print(df_explode)
"""
     A  B  C
0    1  1  1
0    2  1  1
0    3  1  1
1  foo  1  2
2  NaN  1  3
3    3  1  4
3    4  1  4
"""

めちゃくちゃお手軽ですね。
前の記事で書いていたようにappendの遅さに文句を言ったり、自分で配列を作るコードを書いたりと言ったことは全くしなくて良くなりました。

boto3でEC2インスタンスを起動してIPアドレスを取得する

EC2のインスタンスを操作するとき、(会社ではCLIのバッチファイルを手元に持ってるのですが)私物の環境ではいつもコンソールにログインして起動/停止していたので、
これもバッチ化することにしました。
AWS CLIではなく、 Pythonライブラリの boto3で作ってみます。

職場の環境と異なり、自分の学習環境のEC2はIPアドレスを固定していません。(お金かかるから。)
なので、毎回コンソールから起動して、IPアドレスを確認し、そのIPアドレスに接続する、という作業を行っていました。
これを短縮するため、起動したらIPアドレスを取得して表示できるようにします。

ドキュメントはこの辺りが参考になります。
ec2.html#instance

以下のように、ec2インスタンスのオブジェクトを用意します。


import boto3

ec2 = boto3.resource('ec2')
instance = ec2.Instance('{インスタンスID}')

そして、startで起動してwait_until_running()で起動完了を待ち、
public_ip_addressを取得すれば良いです。

完成したバッチファイルの中身は次のようになります。
これを.pyファイルとして保存して、実行できるように権限を744にします。


#!/usr/bin/env python
import boto3
instance_id = "{インスタンスID}"

ec2 = boto3.resource('ec2')
instance = ec2.Instance(instance_id)
print("インスタンス起動開始")
instance.start()
instance.wait_until_running()
print("インスタンス起動完了")
ip = instance.public_ip_address
print(f"IPアドレス: {ip}")

実行するときちんと、
インスタンス起動開始
インスタンス起動完了
IPアドレス: xx.xxx.xxx.xxx
が表示されました。

ついでですが、停止バッチは次のようになります。


#!/usr/bin/env python
import boto3
instance_id = "{インスタンスID}"

ec2 = boto3.resource('ec2')
instance = ec2.Instance(instance_id)
print("インスタンス停止開始")
instance.stop()
instance.wait_until_stopped()
print("インスタンス停止完了")

Amazon Aurora Serverlessを使ってみる

ずっと前から気になっていたまま、使ったことがなかったのですが重い腰を上げて Aurora Serverless を触ってみることにしました。

用途は仕事ではなく、自分の趣味と勉強でとあるデータを蓄積するDBです。
AWSのアカウント持っていてDBが必要なら、RDSを使うのが順当なのですが、
通常のRDSは個人で使うにはちょっとお高いので、これまではEC2に導入したMySQLを使っていました。
そこにAurora の Serverless が登場ということで、自分の分析作業時のみの課金で使えるとなれば非常にお得な気がします。
完全に移行できるかとコストはトータルどうなるか、といった懸念は残りますが、まずは一度触ってみることにしました。

Aurora Serverless にはいくつか制限事項があるようです。
それを満たせるように事前に準備を進めていきます。

詳細はこちらを参照: Aurora Serverless の制約事項

1. VPC (Virtual Private Cloud)

Aurora Serverless にパブリックなIPアドレスを割り当てることはできず、おなじVPC内からしかアクセスできないそうです。
なので、ローカルの端末から踏み台等使わずに直接繋ぐことはできなさそうですね。
また、EC2インスタンスををクライアントにする場合は、おなじVPCの中に置いておく必要があります。
(僕はVPCはデフォルトの1個しか使っていないので、この制限は特に意識することはありませんでした。
VPCを複数使っている人は注意が必要です。)

2. AWS PrivateLink エンドポイント

僕がこの辺りの用語に疎いので、ドキュメントをそのまま引用します。
各 Aurora Serverless DB クラスターには、2 つの AWS PrivateLink エンドポイントが必要です。VPC 内の AWS PrivateLink エンドポイントが制限に達した場合、その VPC にそれ以上 Aurora Serverless クラスターを作成することはできません。
要は、VPCにサブネットを2つ以上用意しておく必要があります。
これも自分の場合は元々東京リージョンに3個持っていたので特に作業の必要はありませんでした。

3. セキュリティグループ

ドキュメントの通り、3306番のポートを利用するので、「インバウンド」で、3306番ポートが開通したセキュリティグループが必要になります。
セキュリティグループの設定画面で「タイプ」に「MYSQL/Aurora」を選択すると自動的に必要な設定が入るので作っておきます。

4. クライアント

実際の利用にはDBに接続するクライアントが必要です。
MySQLか、その互換のMariaDBクライアントが入ったインスタンスを同じVPC内に立てておきましょう。

さて、準備が終わった後、実際に DBを作成するのですが、これは簡単でした。
手順にすると多いですが画面に沿って進むだけなのでほぼ迷いません。

1. AWSのコンソールにログインし、RDSの管理画面に移動する。
2. [データベースの作成]をクリック
3. 標準作成を選択 (簡単作成でも良い)
4. エンジンのタイプ は [Amazon Aurora]を選択
5. エディション は [MySQLとの互換性を持つ Amazon Aurora]
6. MySQLのバージョンを選ぶ。
  これは、ドキュメントで指定されているバージョンでないと、次の選択肢からサーバレスが消えるので注意が必要です。

7. データベースの機能 は [サーバーレス]
8. DBクラスター識別子 は何か名前をつける。
9. マスターユーザー名 を指定 (デフォルトは admin)
10. パスワードの設定。 (自分はパスワードの自動作成にしました)
11. キャパシティーの設定を変更。(予算を抑えるため気持ち低めにしました。)
12. [データベースの作成]をクリック

ここまで進むとDBの作成が始まり、数分でDBが出来上がります。
出来上がったら、[認証情報の詳細を表示] から、 adminのパスワードを入手します。
また、同時に エンドポイント もわかるのでこれも記録しておきます。

DBが作成できたら、クライアントの環境から以下のコマンドで接続できます。


mysql -h {エンドポイント} -u {ユーザー名} -p

Enter password: 
と聞かれるのでパスワードを入力する。

ポートはデフォルトの3306を使っているので、 -P 3306 はつける必要ありません。(つけても大丈夫ですが。)

これで、通常のDBとして、使用できるようになりました。

もしDBが作成できているのに接続できなかった場合、セキュリティグループを見直してみてください。
(僕は用意していたセキュリティグループと違うグループが付与されていてしばらく詰まりました。)

あとは、残る課題はお値段ですね。
しばらく使ってみて、どのくらいの金額になるのか様子をみようと思います。

※ 以下、追記
2~3日ほど放置した後、様子を見たらメキメキと課金されていました。触っていない間も稼働しっぱなしだったようです。

設定項目の中に、「数分間アイドル状態のままの場合コンピューティング性能を一時停止する」
というがあり、これにチェックを入れないと、期待してた使っていない間は停止する効果が得られないようです。
てっきりデフォルトだと思っていたので危なかったです。
(請求金額アラートに救われました)