找到一个斜率变化点作为自由参数 - Python

时间:2017-07-12 16:35:45

标签: python data-fitting

假设我有两个数据列表如下:

x = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
y = [1, 2, 3, 4, 5, 6, 8, 10, 12, 14]

也就是说,非常明确的是,仅仅为这些数据拟合一条线并不起作用,而是在数据中的某一点改变了斜率。 (显然,人们可以很容易地从这个数据集中找出那个变化的地方,但是在我使用的集合中并不那么清楚,所以让我们忽略它。)带有衍生物的东西。 ,我猜测,但这里的重点是我想把它当作一个自由参数,我说"这一点,+ / - 这个不确定性,这里是线性斜率之前并在此之后。"

注意,如果它更容易,我可以用数组做到这一点。谢谢!

4 个答案:

答案 0 :(得分:3)

以下是您的数据图表:

enter image description here

你需要找到两个斜率(==取两个导数)。首先,找到每两个点之间的斜率(使用numpy):

import numpy as np 
x = np.array([1, 2, 3, 4, 5, 6, 7, 8, 9, 10],dtype=np.float)
y = np.array([1, 2, 3, 4, 5, 6, 8, 10, 12, 14],dtype=np.float)
m = np.diff(y)/np.diff(x)
print (m)
# [ 1.  1.  1.  1.  1.  2.  2.  2.  2.]

显然,斜率在第六个间隔(第六个和第七个点之间)从1变为2。然后取这个数组的导数,它告诉你斜率何时改变:

print (np.diff(m))
[ 0.  0.  0.  0.  1.  0.  0.  0.]

要查找非零值的索引:

idx = np.nonzero(np.diff(m))[0]
print (idx)
# 4

由于我们对x采用了一个导数,并且索引在Python中从零开始,idx+2告诉您在第六点之前和之后的斜率不同。

答案 1 :(得分:2)

您可以将斜率计算为每对点之间的差异(一阶导数)。然后检查斜率变化的位置(二阶导数)。如果它发生变化,请将索引位置附加到# Copyright 2015 Google Inc. All Rights Reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # [START app] import logging from datetime import datetime current_time = str(datetime.now()) from flask import Flask app = Flask(__name__) @app.route('/') def hello(): """Return a friendly HTTP greeting.""" return 'Hello World! The time is ' + current_time message = "this worked, as of " + current_time + "\n" with open("test.txt", "a") as myfile: myfile.write(message) @app.errorhandler(500) def server_error(e): logging.exception('An error occurred during a request.') return """ An internal error occurred: <pre>{}</pre> See logs for full stacktrace. """.format(e), 500 if __name__ == '__main__': # This is used when running locally. Gunicorn is used to run the # application on Google App Engine. See entrypoint in app.yaml. app.run(host='127.0.0.1', port=8080, debug=True) # [END app] ,即斜率变化的点集合。

请注意,第一个点没有唯一的斜率。第二对点将给出斜率,但在测量斜率变化之前需要第三对点。

idx

当然,这可以在Pandas或Numpy中更有效地完成,但我只是给你一个简单的Python 2解决方案。

简单的条件列表理解也应该非常有效,尽管它更难理解。

idx = []
prior_slope = float(y[1] - y[0]) / (x[1] - x[0])
for n in range(2, len(x)):  # Start from 3rd pair of points.
    slope = float(y[n] - y[n - 1]) / (x[n] - x[n - 1])
    if slope != prior_slope:
        idx.append(n)
    prior_slope = slope

>>> idx
[6]

答案 2 :(得分:1)

我不太清楚你想要什么,但你可以通过这种方式看待进化(衍生物):

>>> y = [1, 2, 3, 4, 5, 6, 8, 10, 12, 14]
>>> dy=[y[i+1]-y[i] for i in range(len(y)-1)]
>>> dy
[1, 1, 1, 1, 1, 2, 2, 2, 2]

然后找到它改变的点(二阶导数):

>>> dpy=[dy[i+1]-dy[i] for i in range(len(dy)-1)]
>>> dpy
[0, 0, 0, 0, 1, 0, 0, 0]

如果你想要这一点的索引:

>>> dpy.index(1)
4

可以给出斜率变化前最后一个点的值:

>>> change=dpy.index(1)
>>> y[change]
5

在您的y = [1, 2, 3, 4, 5, 6, 8, 10, 12, 14]中,更改发生在索引[4](列表索引开始为0),此时y的值为5

答案 3 :(得分:0)

Knee point 可能是一个潜在的解决方案。

from kneed import KneeLocator
import numpy as np 
x = np.array([1, 2, 3, 4, 5, 6, 7, 8, 9, 10])
y = np.array([1, 2, 3, 4, 5, 6, 8, 10, 12, 14])
kn = KneeLocator(x, y, curve='convex', direction='increasing') 
# You can use array y to automatically determine 'convex' and 'increasing' if y is well-behaved
idx = (np.abs(x - kn.knee)).argmin()

>>> print(x[idx], y[idx])
6 6