ポイント
- 関数にはリスト型やnumpy.array型の多次元配列を引数として指定することができる。
- pandas.DataFrameを関数に入れて、まとまった処理をすることができる。
- 多変数関数は、引数を x => x, y のように記述するだけで簡単に実装できる。
- 多変数関数の場合(ここでは簡単に2変数x, yの関数としよう)、引数のx, yが多次元配列であるとき、x, yの次元・データの型は同じでなければならない。
- すなわち、関数の引数は、さまざまな変数の数・多次元配列のデータを指定することができる。
- z=f(x, y)とした場合、出力されるzはx, yと同じ型となる。x, yが数値であれば1つの数値zが出力されるし、x, yが2行3列の行列ならば1つの2行3列の行列zが出力される。
目的1
リストやnumpy配列を関数の引数として指定する方法を解説します。
目的2
以前、2次元ガウス関数を扱う記事を書いた際に、多変数関数の実装にはいくらか注意すべき点があることに気づき、本記事を執筆するに至りました。
今回は、こちらの記事で取り扱った、2次元のガウス関数を例に多変数関数の実装方法と注意点を解説していきます。x, yの2つの変数を持つガウス関数は、次のように表すことができます。
$$f(x, y)=A\mathrm{exp}\left(-\frac{(x-\mu_x)^2}{2\sigma_x^2}\right)\mathrm{exp}\left(-\frac{(x-\mu_y)^2}{2\sigma_y^2}\right)$$
また、関数を次のような形で実装ことができます。
def gauss_2d(x, y, A, sigma_x, sigma_y, mu_x, mu_y): # 2D Gaussian
z = A * np.exp(-(x-mu_x)**2/(2*sigma_x**2)) * np.exp(-(y-mu_y)**2/(2*sigma_y**2))
return z
目的3
PandasのDataFrameを関数の引数として指定し、データの抽出を行う方法を解説します。
1. 単純な値の代入
2つの変数x, yに対し、それぞれ1つずつ値を代入することで、値zが出力されます。
x = -1
y = -1
A = 1
sigma_x = 1
sigma_y = 1
mu_x = 0
mu_y = 0
gauss_2d(x, y, A, sigma_x, sigma_y, mu_x, mu_y)
>> Out: 0.36787944117144233
2. リスト型も代入できます
x, yに1つずつの値を代入できるなら、2つずつ代入、3つずつ代入といったことも可能です。
def multi_values(x,y):
print(x)
print(y)
x = [1,2,3]
y = [4,5,6]
multi_values(x, y)
>> [1,2,3]
[4,5,6]
しかし、今回のガウス関数の場合、次のようなエラーが出てしまいます。
x = [-1, 0, 1]
y = [-1, 0, 1]
A = 1
sigma_x = 1
sigma_y = 1
mu_x = 0
mu_y = 0
gauss_2d(x, y, A, sigma_x, sigma_y, mu_x, mu_y)
>> TypeError: unsupported operand type(s) for -: 'list' and 'int'
そこで、コードを次のように書き換える必要があります。
def gauss_2d(x, y, A, sigma_x, sigma_y, mu_x, mu_y): # 2D Gaussian
x = np.array(x)
y = np.array(y
z = A * np.exp(-(x-mu_x)**2/(2*sigma_x**2)) * np.exp(-(y-mu_y)**2/(2*sigma_y**2))
return z
3. numpy配列であるarrayも代入できます
複数の値をもつ変数を代入するためには、numpyのarray配列を用います。
x = np.array([-1, 0, 1])
y = np.array([-1, 0, 1])
gauss_2d(x, y, A, sigma_x, sigma_y, mu_x, mu_y)
>> Out : array([0.36787944, 1. , 0.36787944])
この時、x, yのデータ数は等しくなければなりません。そして、各x, yに対応する出力z=f(x, y)が出力されます。つまり、この例の場合、x, yのデータ数はそれぞれ3なので、x, yを関数gauss_2dに代入して出力される値も3つとなるわけです。
4. numpy配列は多次元でも良いのか
関数には、numpy.arrayを用いれば、1行n列の行列(すなわちベクトル)を代入できることを上で示しました。同様に、m行n列の行列、すなわち多次元配列も代入可能です。
X = np.array([[-1, 0, 1],[-2, 0, 2]])
Y = np.array([[-1, 0, 1],[-2, 0, 2]]
gauss_2d(x, y, A, sigma_x, sigma_y, mu_x, mu_y)
>> Out : array([[0.36787944, 1. , 0.36787944],
[0.01831564, 1. , 0.01831564]])
今回扱う関数の場合、入力データの出力結果はx, yの型と全く同じになります。そのため、X, Y が2行3列の行列であれば、出力zも2行3列で出力されます。
5. DataFrame型のデータも代入できます
引数には、pandasのデータフレームを指定することも可能です。
csvデータに対して何度も繰り返す操作をしたいとき、DataFrameに対して使用する関数を作成しておくと便利です。
気象データを例に解説
次のような気象データがあるとします。0, 1, 2は、例えばある地点の名前だと考えましょう。
climate = {"気温":[24, 26, 27.5],
"気圧":[1005, 1007, 998],
"湿度":[55, 45, 60]}
df_climate = pd.DataFrame(climate)
>> 気温 気圧 湿度
0 24.0 1005 55
1 26.0 1007 45
2 27.5 998 60
def data_frame_func(df):
temp = df["気温"]
pressure = df["気圧"]
humidity = df["湿度"]
return temp, pressure, humidity
これにたいして、気温、気圧、湿度のデータをそれぞれ抽出するには、次のような関数を実装すればよいです。配列が出力されるので、
出力[0] = 気温データ, 出力[1] = 気圧データ, 出力[2] = 湿度データ
のように、欲しいデータを取得することができます。
def data_frame_func(df):
temp = df["気温"]
pressure = df["気圧"]
humidity = df["湿度"]
return temp, pressure, humidity
import pandas as pd
climate = {"気温":[24, 26, 27.5],
"気圧":[1005, 1007, 998],
"湿度":[55, 45, 60]}
df_climate = pd.DataFrame(climate)
result = data_frame_func(df_climate)
print(df_climate)
print("temp(℃): ", result[0])
print("pressure(hPa): ",result[1])
print("humidity(%): ",result[2])
>> temp(℃):
0 24.0
1 26.0
2 27.5
Name: 気温, dtype: float64
pressure(hPa):
0 1005
1 1007
2 998
Name: 気圧, dtype: int64
humidity(%):
0 55
1 45
2 60
Name: 湿度, dtype: int64
コメント