😺
pandas で線形フィットを行う かつ 対応する値を計算する
pandas で線形フィットを行う かつ 対応する値を計算する
コード
import pandas as pd
import numpy as np
import time
# 仮のデータフレームを作成
start_x = 10
start_y = 100
num = 150000
df = pd.DataFrame({
'x': np.arange(start_x, start_x+num),
'y': np.arange(start_y, start_y+num) + np.random.randn(num)
})
# 'x'列と'y'列に対して1次の多項式フィットを行う
coeff = np.polyfit(df['x'], df['y'], 1)
# 線形フィットの計算値 (やり方1)
start = time.time()
df["fit"] = df['x'].apply(vfunc)
diff1 = time.time() - start
# 線形フィットの計算値 (やり方2)
vfunc = np.vectorize(lambda x: coeff[0] * x + coeff[1])
start = time.time()
df["fit2"] = vfunc(df['x'])
diff2 = time.time() - start
# 線形フィットの計算値 (やり方3)
start = time.time()
df["fit3"] = np.polyval(coeff, df['x'])
diff3 = time.time() - start
df["error"] = (df['fit'] - df['y']).abs()
df["rate%"] = (df['error'] / df["y"]) * 100
print(df)
print(diff1)
print(diff2)
print(diff3)
説明
np.polyfit で線形フィットする。戻り値で ax + b
の (a, b)
の部分を返す。
np.vectorize で普通の関数をベクター関数化する。ここでは lambda 関数を渡す。
やり方1
dataframe の apply で引数で渡した関数 (ここでは vfunc
) を指定した列に適用する。
df["fit"]
が 線形フィットした値になる。
やり方2
vfunc(df['x'])
で df['x']
の各列に対して線形フィットした値を求める。
df["fit2"]
が 線形フィットした値になる。
やり方3 (最速)
np.polyval で引数に dataframe の列を渡す。
出力例
x y fit fit2 fit3 error rate%
0 10 100.291546 100.002049 100.002049 100.002049 0.289497 0.288655
1 11 102.088520 101.002049 101.002049 101.002049 1.086471 1.064244
2 12 101.339129 102.002049 102.002049 102.002049 0.662919 0.654159
3 13 104.631109 103.002049 103.002049 103.002049 1.629060 1.556956
4 14 103.962152 104.002049 104.002049 104.002049 0.039896 0.038376
... ... ... ... ... ... ... ...
149995 150005 150095.398152 150095.004077 150095.004077 150095.004077 0.394075 0.000263
149996 150006 150096.283725 150096.004077 150096.004077 150096.004077 0.279648 0.000186
149997 150007 150095.972876 150097.004077 150097.004077 150097.004077 1.031201 0.000687
149998 150008 150098.102642 150098.004077 150098.004077 150098.004077 0.098565 0.000066
149999 150009 150100.863748 150099.004077 150099.004077 150099.004077 1.859670 0.001239
[150000 rows x 7 columns]
0.9963786602020264
0.04494190216064453
0.0010008811950683594
Discussion