假设我有两个数据列表,如下所示:
x = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
y = [1, 2, 3, 4, 5, 6, 8, 10, 12, 14]
也就是说,很明显,仅仅将一条直线拟合到这些数据上是行不通的,而是在数据中的某个点改变了坡度。(很明显,我们可以很容易地从这个数据集中找出变化的位置,但在我正在处理的数据集中并不是很清楚,所以我们忽略它。)我猜,关于导数的一些东西,但这里的重点是我想把它当作一个自由参数,我说"这是这个点,+/-这个不确定性,这里是前面的线性斜率。在这一点之后。"
注意,如果数组更简单的话,我可以用它来做这个。谢谢!
我不太清楚你的问题。是否要查找两个斜面开始不同的索引?你说的不确定性是什么意思?为什么斜坡是一个自由参数?它在每两个(连续)点之间定义。
顺便说一句,在Python中没有数组这样的东西。请参阅:/questions/1514553/…
@当然,还有阵列。
@Sumnerevans有一些阵列,例如内置的array.array和功能更全面的numpy.ndarray。后者仅用于科学/数值计算领域,前者更为罕见。然而,人们将list称为数组是一个很常见的错误。
@随机化,这是一个必须导入的模块,而不是像list那样的语言的核心、一流部分。
@它是标准图书馆的一部分。仅仅因为它位于与__builtins__不同的名称空间中,并不会使它成为Python的一部分。Numpy是第三方扩展,尽管核心python语言有明确添加的功能来帮助Numpy。例如,椭圆单子:...。
@Sumnerevans,有没有听过"包括电池"这句话?如果array在标准的python库中,您还需要什么?对于每个可能的函数和数据类型都是内置的?接下来你会说,在Python3中,reduce不再是"核心"。
回复:有不确定性的问题,数据集中的IRL,不太可能像我提供的数据一样有明显的变化。相反,它是随时间变化的流量,所以拟合并不完美,所以很可能是"变化在第10天加上或减去两天"。
以下是您的数据图:
。
你需要找到两个斜率(=取两个导数)。首先,找出每两点之间的坡度(使用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告诉您,在第六点之前和之后的斜率是不同的。
我想这就是我想要的-谢谢!我想这在数组中更容易处理,所以我想不出该如何处理。
很高兴听到这个消息!:)别忘了接受它作为答案!;)
会的。只是想知道,所以IRL我使用的数据并不像这个例子那么完美-它是一个通量测量,会在几天内变化,所以我怀疑答案是"斜率变化是在第10天,加减两天。"你知道吗,有一个聪明的方法来计算?谢谢!
如果我们有一些小样本数据,我们可以修改这个答案。但你认为在某些时间间隔内,np.diff(m)为零吗?
您可以将坡度计算为每对点之间的差(一阶导数)。然后检查坡度变化的位置(二阶导数)。如果它发生变化,将索引位置附加到idx中,即坡度变化点的集合。
请注意,第一个点没有唯一的坡度。第二对点会给你一个坡度,但是你需要第三对点才能测量坡度的变化。
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]
当然,在熊猫或麻木的环境中,这可以更有效地完成,但我只是给您一个简单的python 2解决方案。
一个简单的条件列表理解也应该是相当有效的,尽管它更难理解。
idx = [n for n in range(2, len(x))
if float(y[n] - y[n - 1]) / (x[n] - x[n - 1])
!= float(y[n - 1] - y[n - 2]) / (x[n - 1] - x[n - 2])]
。
所以,我没有意识到我需要具体说明我可以用麻木或者熊猫来做这件事。你也会怎么用呢?只是好奇。
我不太清楚你想要什么,但是你可以用这种方式看到进化过程(导数):
>>> 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。