在数据框列上应用curve_fit

时间:2015-08-06 23:03:30

标签: python pandas scipy

我有一个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

我可以应用该函数并获得一个数组作为回报:

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类似的内容完成吗?

3 个答案:

答案 0 :(得分:1)

希望我的解决方案适合你。

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

答案 1 :(得分:0)

我认为问题在于你的拟合函数的应用会返回一个昏暗的3x3数组(conner返回的3个fitparameters)。但是预计会像你的df那样形成20x3的形状。

因此,您必须在这些参数上重新应用fitfunction以获得拟合的y值。

h1:after {
    content: 'Hello\AWorld';
    white-space:pre;
}

有关更多示例,请查看here

答案 2 :(得分:0)

(本文基于先前的两个答案,并提供了一个完整的示例,其中包括对fit参数的数据帧构造的改进)

以下函数fit_to_dataframe将任意函数拟合到数据中的每一列,并以方便的格式返回拟合参数(此处忽略协方差):

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'])

fit参数的可用形式如下:

          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笔记本here获得。