Ruby – クラス~initialize

基本

Rubyのクラスのコンストラクターはinitialize()

initialize()ではなくインスタンスメソッド内でプロパティーを定義することもできる。

ただしこの場合には、プロパティーが定義されるメソッドをプロパティーが参照される前に呼んでおかなければならない(そうしないと演算などで未定義でエラーになる)。

なので、普通はインスタンス生成時に自動的に呼ばれるinitialize()内でプロパティーを定義するのが安全。

オーバーロード不可

異なる引数のコンストラクターを意図してオーバーロードすることはできない。

上記のコードの場合、後の方で定義したコンストラクターは使える。

引数のパターンを変えたいときは、デフォルト引数可変長引数を用いるとよい。

 

Ruby – 関数

関数の定義

関数はdef...endで定義する。その関数が呼び出されるより前に定義されていなければならない。

関数の戻り値

return文で関数の戻り値を指定できる。

再帰呼び出し

再帰呼び出しにも対応。

デフォルト引数

あまりよくない方法

引数のデフォルト値をPythonと同じように指定できる。

実行時に指定した引数は、デフォルト引数があっても引数の順に入れ替えられる。以下の例の8行目で2つの仮引数に対して1つの実引数を与えているが、その値は1つ目の引数に使われている。

以下の6行目で仮引数名yzを指定して実引数を渡しているが、それらの値はxyに与えられてしまう。これは以下の流れによるものと考えられる。

  • 実行時に与えた引数は、デフォルト引数の有無にかかわらず先頭から順番に与えられる
  • 実行時に指定した引数'y=7''z=8'はそれぞれ式として評価され、その値が7、8となる
  • この2つの値が仮引数の先頭から与えられx=7y=8となり、zはデフォルト値の3が使われる

妥当な方法~キーワード引数

仮引数名を指定して実引数を渡す場合は、以下のようにキーワード引数を使うとよい。ただしキーワード引数で仮引数を指定した場合、実行時には指定を省略してデフォルト値を使うか、仮引数を明示して引数を与える必要がある。

デフォルト値を指定しない仮引数と、デフォルト値を指定したキーワード引数は混在して利用可能。

可変長引数

引数の頭に'*'をつけると配列とみなされ、複数の引数を渡せる。

配列の要素を使った処理の例。

通常の引数と可変長の引数が混在する場合、少なくとも通常の引数に対応する引数を渡す必要がある。

可変長引数の内容は空でもよく、まず通常の引数が埋められた後、その数を超える引数が可変長引数となる。

 

Ruby – 条件分岐

if~end節

基本形

一般的なif文の書き方で条件が真のときにthen節が実行される。必ずendで閉じる

else

else節も同じ。

elsif

elseifではなくてelsif

thenの省略

if節やelsif節の後のthenは省略可能。

一行で書く

一行にまとめることは可能。ただしthenがないとエラーになる。

';'で区切ると正常に実行される。

値を返す

if文は条件に対応した節の値を持つ。

後置

実行文の後にif文を置くと、条件が真の場合に文が実行される。

unless文

基本

unlessは条件が真でなければ(偽のときに)then節が実行される。

else

unless文のelse節は条件が真の時(偽でないとき)に実行される。

一行で書く

if文と同じく一行にまとめられる。

後置

実行文の後にunless文を置くと、条件が偽の場合に文が実行される。

case文

基本

case文は複数の条件を順番に確認していく。

thenの省略

thenは省略できる。

値を返す

case文は真となった条件の節の値が戻り値となる。

 

Ruby – 繰り返し処理

繰り返し処理の種類

for~要素を取り出して処理する

Rangeオブジェクトを使った繰り返し処理。".."演算子は両端の値を含む。

"..."演算子は終了値を含まない。

配列の内容を一つずつ取り出す例。

times~回数を指定する処理

timesは繰り返し回数を指定して実行。

繰り返しのカウンターを指定できる。カウンターはゼロからスタートし、指定回数-1までカウントされる。

upto/downto~カウントアップ/ダウン

uptoは初期値から終了値までを含んでカウントアップ。downtoは逆にカウントダウン。カウンターを省略しても可。

step~刻み幅を指定

[初期値].step([終了値], [刻み幅])で実行。

終了値がちょうどでない場合はその手前まで実行される。

ただし浮動小数点の計算誤差があり得るので、ちょっと気持ち悪い。

each~要素を一つずつ取り出す

eachforと同じくコレクションの要素を順に取り出す。

hashはキーと値を取り出せる。

ブロックの省略形{...}がある。

each_with_index~要素番号も取得

each_with_indexはコレクションから要素を取り出しながら、そのインデックスも得られる。Pythonのenumerateと同じ機能。

while~条件が真の間繰り返し

whileは条件が真の間ブロックを繰り返す。

whilebeginendブロックの後に置ける。上記の前置の場合は条件によってはブロックは一度も実行されないが、後置の場合は少なくとも1回は実行される。

until~条件が真になるまで繰り返し

untilwhileと逆で条件が偽の間繰り返し、真になったらループ終了。whileと同様、ブロックの前/後どちらに置いてもよい。

loop~無限ループ

loopは単にブロックを繰り返す。ループの終了判定が必要。

繰り返し制御

break~ループを終了

breakは実行中のループブロックを終了する。

next~残りを飛ばして続ける

nextはそれ以下の実行をせず、ループの次のステップに入る。他言語のcontinueと同じ。

以下の例ではn==2のときだけprintが実行されず、次のn=3の処理に入る。

redo~同じ条件で再実行

redoは現在のループと同じ条件で再度実行する(ループの次のステップではなく同じステップを再実行)。

この例では、n==2の時に"2 - C"を表示。その後n==3となってredoが実行され、a=="C"のままputsから実行、"3 - C"が表示されている。

次の例はすこしややこしい。

この例ではeachn=1とセットされて"1"が表示される。その後n==2となるのでredoが実行され、n==2のままprintが実行されて"2"が表示。その後n==3になるので次のeachに移り、n==2がセットされる。このn("2")を表示した後、n==3となるのでredoは実行されず・・・と続く。

 

Ruby – 変数と定数

変数の先頭はアルファベット小文字。任意のオブジェクト(の参照番地)を代入可能。

定数は先頭がアルファベット大文字。定数に値を代入しようとするとwarning。

 

Ruby – 演算子

算術演算子

単項演算子

算術演算子と括弧

除算は被除数・除数とも整数の時は小さい側の整数に丸められる(floor)。いずれかあるいは両方が実数の時は実数になる。

'%'で剰余を計算。

'**'でべき乗を計算。

文字列演算子

結合

'+'演算子は2つの文字列の結合結果を返し、元の文字列は保持される。

'<<'演算子は2つの文字列の結合結果を返し、1つ目の変数を結合結果で書き換える。

'*'演算子は文字列を繰り返して複製して結合。

ビット演算子

'~'は前値の否定演算子。

’&’’|’'^'はそれぞれAND、OR、XOR。

'<<''>>'は指定した数だけシフトする演算子。

数値比較演算子

数値の比較演算子は標準的な定義。

文字列比較演算子

論理演算子

'!'は前値の否定演算子。

'&&''||'は論理積、論理和。

'and''or'も論理積、論理和だが挙動が異なる。

andor演算子は他の殆どの演算・処理に対して優先度が低いため、演算子より前の項がまず実行されてから2項目との評価が行われるため。括弧で優先順位を明示すると&&||と同じ結果になる。

三項演算子

三項演算子の形。

使用例。

 

Ruby – 基本的なリテラル

数値

整数

基数を指定する場合。

先頭がゼロの場合は8進数と解釈される点に注意。8進数と解釈できない場合はエラーになる。

実数

小数点以下をゼロとすると実数のリテラルになるが、小数点のみを付けるとエラーになる。

0~1の小数点では、先頭のゼロは省略できない。

有理数

末尾に'r'を付けると有理数となり、分数形式で保持される。

複素数

'i'の直前に数値を並べると虚数となり、複素数形式で保存される。

文字列

ダブルクォートかシングルクォートで囲む。

ダブルクォートで囲むとバックスラッシュ記法は特殊文字として解釈されるが、シングルクォートで囲むとバックスラッシュが単なる文字として扱われる。

空白をはさんで並んだ文字列は結合される。

文字リテラル

'?'に続く一文字は文字列として扱われる。

ヒアドキュメント

'<<[識別子]'の次の行から'[識別子]'の直前の行までが複数行にわたる文字列として解釈される。

論理値

論理値のリテラルとしてtruefalseが定義されている。

 

Axes.set_xlabel/ylabel~軸のラベル

概要

Axesに描いたグラフの軸にラベルを付けるには、set_xlabel()set_ylabel()を使う。

位置等の調整

ラベルの位置はlocパラメーターで調整する。x軸とy軸では設定値が異なる(matplotlibのバージョンが3.1.1ではエラーになるので、3.3.1にアップグレード)。

set_xlabel("labelname", loc='left'/'center'/'right')
set_ylabel("labelname", loc='bottom'/'center'/'top')

以下の例では、set_ylabel()のパラメーターにTextのプロパティーとしてrotationを指定している(そのままだと横にしたラベルがエリア外に切れてしまうので、8行目でsubplots_adjustを指定している)。

pyplot – subplotの位置調整

subplot間の間隔調整

Figure内のSubplotの位置や相互の間隔を調整するには、subplots_adjust()メソッドを用いる。pyplot.subplots_adjust()でもよいが、figureのメソッドとしてもよい。

pyplot.subplots_adjust(left, bottom, right, top, wspace, hspace)
left, bottom, right, topsubplots全体の左端、下端、右端、上端の位置。wspace, hspaceはそれぞれ各subplot間の幅方向と高さ方向の間隔。

引数の意味はドキュメントで以下のように説明されている。

left~topはキャンバスの左上を(0, 0)、右下を(1, 1)としたときの比率。

たとえばデフォルトで4つのsubpotsを描く。

これに対してsubplots全体の左端をキャンバス内の左から0.3の位置に、下端を下から0.5の位置に設定すると以下のようになる。

また、wspace、hspaceを1とすると以下のようになる。

 

Python – How to do what I want to do

リスト関係

2次元リストを展開して1次元リストにしたい

itertools.chain.from_iterableを使う。

 

 

2次元リストを転置したい

2次元のリストを転置する方法を、順を追って確認する。

まず2次元リストの要素、すなわち各行を取り出す。リストの要素を分解するにはリストの先頭に'*'をつける。

結果はリストやタプルではなく、独立した3つの子リストが取り出されている。

これらの結果は、zip関数の任意個数の引数として与えることができる。ただしその結果はタプルとして得られる。

この結果を内包表記を使って1つのリストにまとめると、3つのタプル行を含むリストになる。

各行をタプルではなくリストとしたいので、list関数でタプルをリストに変換する。

これで元の2次元リストが転置された。

ndarray関係

1次元配列の2次元化

1次元配列を単に2次元化

1次元配列を2次元一要素の行ベクトルにする方法。

  • np.array([a])と2次元で構築する
  • reshape(1, -1)で2次元1行の配列として変形

1次元配列の列ベクトル化

1次元配列を2次元の列ベクトルにする方法。hstack()などで列ベクトルを横に結合していくときに必要。

  • reshape(-1, 1)でn行1列の配列として変形

2つの1次元配列の結合

縦に積み重ねる

素直に実行するならvstack()を使うのがおすすめ。

  • vstack()は1次元配列のままで積み重ねられる
  • append()は1次元配列を2次元化する必要がある

列ベクトルとして横につなげていく

この場合はhstack()が意外にややこしく、c_が手軽。ただし列ベクトルを意識するならhstack()もアリ。

  • 1次元配列をreshape()で列ベクトル化し、hstack()を使う(1次元配列のままだと横1列に伸びるだけ)
  • c_を使う(1次元配列でも列ベクトル化されて結合される)

空のベクトルへの追加

1次元配列の縦方向への追加

縦方向に追加するならvstack()が全般によさそう。

empty((0, n), dtype=type)で空の配列を準備し、これにvstack()で1次元配列をそのまま追加していく。

1次元配列を列ベクトルとして横方向に追加

empty((n, 0), dtype=type)で空の配列を準備し、1次元配列をreshape()で列ベクトルに変形してhstack()で追加していく。

または、c_を使うとreshape()を使わなくてもそのまま列ベクトルとして追加してくれる。

多次元配列の1次元化

2次元以上の配列を1次元としたいときは、reshape(-1)、flatten()、ravel()メソッド/関数を使う(詳しくはこちら)。

たとえばpyplotのsubplotで2次元の配列として得られたAxesオブジェクト(への参照)に対して全て同じ処理を施したいときに、以下のようにする。

条件による抽出

条件に合う要素を取り出す

条件式による要素の取り出しを参照。

条件に合う要素のインデックスを取り出す

1次元配列の条件に合う行を2次元配列から切り出す

特徴量データの配列のうち、特定のクラスに属するデータだけを取り出したいときなど。

インデックス配列の置き換え

例えばclass_name = np.array(["Class-0", "Class-1", "Class-2"])と定義されているとき、配列np.array([0 1, 2, 0])の各要素をインデックスとしてclass_nameの要素で置き換えたい(numpy.ndarray(['Class-0', 'Class-1', 'Class-2', 'Class-0'])を得たい)。

インデックス配列の置き換えを参照。

統計値の計算

min, max, argmin, argmax

1次元配列のmin()メソッド/max()メソッドを使うと、要素の中の最小値/最大値が得られる。また、argmin()メソッド/argmax()メソッドを使うと、最小の要素/最大の要素のインデックスが得られる。

2次元配列の場合は、a.reshape(-1).min()a.reshape(-1).argmin()などと同じ結果となる。

メソッドの引数でaxis=0を指定すると、各列ごとの最小値/最大値を要素とする1次元配列を得る。

axis=1を指定すると、各行ごとの最小値/最大値を要素とする1次元配列を得る。この場合、この配列を列ベクトルとして考えると対比がわかりやすい。

sum,mean

要素の和や平均を計算するsum()メソッド/mean()メソッドもmin()max()と同じように機能する。

1次元配列の場合。

2次元配列の場合は全要素で計算したスカラーを返す。

axis=0で列ごとに計算した結果を1次元配列で返す。

axis=1で行ごとに計算した結果を1次元配列で返す。この配列が列ベクトルだと解釈すると分かりやすい。

順列や組み合わせを得たい

概要

順列や組み合わせの結果としての要素のコレクションを得たいときは、itertoolsパッケージ使い、結果のイテレーターをforループなどで利用。

要素数(選び出す個数)指定のパラメーター名や省略時の挙動がそれぞれで異なっているので注意。

直積

itertools.product()で直積のイテレーターを得る。

順列

itertools.permutations()で順列のイテレーターを得る。

組み合わせ

itertools.combinations()で組み合わせのイテレーターを得る。

重複組み合わせ

combinations_with_replacement()で重複ありの組み合わせのイテレーターを得る。