在数据框列上应用 curve_fit
Apply curve_fit on dataframe columns
我有一个包含多个列的 pandas.DataFrame
,我想对每个列应用一个 curve_fit
函数。我希望输出是一个数据框,其最佳值适合列中的数据(目前,我对它们的协方差不感兴趣)。
df 具有以下结构:
a b c
0 0 0 0
1 0 0 0
2 0 0 0
3 0 0 0
4 0 0 0
5 0 0 0
6 1 0 1
7 1 1 1
8 1 1 1
9 1 1 1
10 1 1 1
11 1 1 1
12 1 1 1
13 1 1 1
14 2 1 2
15 6 2 6
16 7 2 7
17 8 2 8
18 9 2 9
19 7 2 7
我定义了一个适合数据的函数:
def sigmoid(x, a, x0, k):
y = a / (1 + np.exp(-k*(x-x0)))
return y
def fitdata(dataseries):
popt, pcov=curve_fit(sigmoid, dataseries.index, dataseries)
return popt
我可以应用该函数并在 return 中得到一个数组:
result_a=fitdata(df['a'])
In []: result_a
Out[]: array([ 8.04197008, 14.48710063, 1.51668241])
如果我尝试 df.apply
该函数,我会收到以下错误:
fittings=df.apply(fitdata)
ValueError: Shape of passed values is (3, 3), indices imply (3, 20)
最终我希望输出如下所示:
a b c
0 8.041970 2.366496 8.041970
1 14.487101 12.006009 14.487101
2 1.516682 0.282359 1.516682
这可以用类似于 apply
的东西来完成吗?
希望我的解决方案对你有用。
result = pd.DataFrame()
for i in df.columns:
frames = [result, pd.DataFrame(fitdata(df[i]))]
result = pd.concat(frames, axis=1)
result.columns = df.columns
a b c
0 8.041970 2.366496 8.041970
1 14.487101 12.006009 14.487101
2 1.516682 0.282359 1.516682
我认为问题在于你的拟合函数的应用 returns 一个暗淡的 3x3 数组(conner 返回的 3 个拟合参数)。但预期的是 20x3 形状的东西作为你的 df。
所以你必须在这些参数上重新应用你的拟合函数来得到你的拟合 y 值。
def fitdata(dataseries):
# fit the data
fitParams, fitCovariances=curve_fit(sigmoid, dataseries.index, dataseries)
# we have to re-apply a function to the coeffs. so that we get fittet
# data in shape of the df again.
y_fit = sigmoid(dataseries, fitParams[0], fitParams[1], fitParams[2])
return y_fit
查看here了解更多示例
(此 post 基于之前的两个答案并提供了一个完整的示例,包括对拟合参数的数据帧结构的改进)
以下函数 fit_to_dataframe
将任意函数拟合到数据中的每一列,并以方便的格式 returns 拟合参数(此处忽略协方差):
def fit_to_dataframe(df, function, parameter_names):
popts = {}
pcovs = {}
for c in df.columns:
popts[c], pcovs[c] = curve_fit(function, df.index, df[c])
fit_parameters = pd.DataFrame.from_dict(popts,
orient='index',
columns=parameter_names)
return fit_parameters
fit_parameters = fit_to_dataframe(df, sigmoid, parameter_names=['a', 'x0', 'k'])
拟合参数的形式如下:
a x0 k
a 8.869996 11.714575 0.844969
b 2.366496 12.006009 0.282359
c 8.041970 14.487101 1.516682
为了检查拟合结果,您可以使用以下函数绘制结果:
def plot_fit_results(df, function, fit_parameters):
NUM_POINTS = 50
t = np.linspace(df.index.values.min(), df.index.values.max(), NUM_POINTS)
df.plot(style='.')
for idx, column in enumerate(df.columns):
plt.plot(t,
function(t, *fit_parameters.loc[column]),
color='C{}'.format(idx))
plt.show()
plot_fit_results(df, sigmoid, fit_parameters)
结果:Output Graph
这个答案也可以作为交互式 jupyter notebook here。
我有一个包含多个列的 pandas.DataFrame
,我想对每个列应用一个 curve_fit
函数。我希望输出是一个数据框,其最佳值适合列中的数据(目前,我对它们的协方差不感兴趣)。
df 具有以下结构:
a b c
0 0 0 0
1 0 0 0
2 0 0 0
3 0 0 0
4 0 0 0
5 0 0 0
6 1 0 1
7 1 1 1
8 1 1 1
9 1 1 1
10 1 1 1
11 1 1 1
12 1 1 1
13 1 1 1
14 2 1 2
15 6 2 6
16 7 2 7
17 8 2 8
18 9 2 9
19 7 2 7
我定义了一个适合数据的函数:
def sigmoid(x, a, x0, k):
y = a / (1 + np.exp(-k*(x-x0)))
return y
def fitdata(dataseries):
popt, pcov=curve_fit(sigmoid, dataseries.index, dataseries)
return popt
我可以应用该函数并在 return 中得到一个数组:
result_a=fitdata(df['a'])
In []: result_a
Out[]: array([ 8.04197008, 14.48710063, 1.51668241])
如果我尝试 df.apply
该函数,我会收到以下错误:
fittings=df.apply(fitdata)
ValueError: Shape of passed values is (3, 3), indices imply (3, 20)
最终我希望输出如下所示:
a b c
0 8.041970 2.366496 8.041970
1 14.487101 12.006009 14.487101
2 1.516682 0.282359 1.516682
这可以用类似于 apply
的东西来完成吗?
希望我的解决方案对你有用。
result = pd.DataFrame()
for i in df.columns:
frames = [result, pd.DataFrame(fitdata(df[i]))]
result = pd.concat(frames, axis=1)
result.columns = df.columns
a b c
0 8.041970 2.366496 8.041970
1 14.487101 12.006009 14.487101
2 1.516682 0.282359 1.516682
我认为问题在于你的拟合函数的应用 returns 一个暗淡的 3x3 数组(conner 返回的 3 个拟合参数)。但预期的是 20x3 形状的东西作为你的 df。
所以你必须在这些参数上重新应用你的拟合函数来得到你的拟合 y 值。
def fitdata(dataseries):
# fit the data
fitParams, fitCovariances=curve_fit(sigmoid, dataseries.index, dataseries)
# we have to re-apply a function to the coeffs. so that we get fittet
# data in shape of the df again.
y_fit = sigmoid(dataseries, fitParams[0], fitParams[1], fitParams[2])
return y_fit
查看here了解更多示例
(此 post 基于之前的两个答案并提供了一个完整的示例,包括对拟合参数的数据帧结构的改进)
以下函数 fit_to_dataframe
将任意函数拟合到数据中的每一列,并以方便的格式 returns 拟合参数(此处忽略协方差):
def fit_to_dataframe(df, function, parameter_names):
popts = {}
pcovs = {}
for c in df.columns:
popts[c], pcovs[c] = curve_fit(function, df.index, df[c])
fit_parameters = pd.DataFrame.from_dict(popts,
orient='index',
columns=parameter_names)
return fit_parameters
fit_parameters = fit_to_dataframe(df, sigmoid, parameter_names=['a', 'x0', 'k'])
拟合参数的形式如下:
a x0 k
a 8.869996 11.714575 0.844969
b 2.366496 12.006009 0.282359
c 8.041970 14.487101 1.516682
为了检查拟合结果,您可以使用以下函数绘制结果:
def plot_fit_results(df, function, fit_parameters):
NUM_POINTS = 50
t = np.linspace(df.index.values.min(), df.index.values.max(), NUM_POINTS)
df.plot(style='.')
for idx, column in enumerate(df.columns):
plt.plot(t,
function(t, *fit_parameters.loc[column]),
color='C{}'.format(idx))
plt.show()
plot_fit_results(df, sigmoid, fit_parameters)
结果:Output Graph
这个答案也可以作为交互式 jupyter notebook here。