Python:在一组数字中找到趋势

Sam*_*ing 26 python math

我在Python中有一个数字列表,如下所示:

x = [12, 34, 29, 38, 34, 51, 29, 34, 47, 34, 55, 94, 68, 81]
Run Code Online (Sandbox Code Playgroud)

找到这些数字趋势的最佳方法是什么?我不想预测下一个数字是什么,我只想输出多组数字的趋势,以便我可以比较趋势.

编辑:根据趋势,我的意思是我想要数字表示数字是增加还是减少以及以什么速率增加.我不是大规模的数学,所以可能有一个合适的名字!

编辑2:看起来我真正想要的是线性最佳拟合的系数.在Python中获取此功能的最佳方法是什么?

Ria*_*zvi 24

可能你的意思是你想在图表上绘制这些数字并找到一条直线,在这条线上,线与数字之间的总距离最小化?这称为线性回归

def linreg(X, Y):
    """
    return a,b in solution to y = ax + b such that root mean square distance between trend line and original points is minimized
    """
    N = len(X)
    Sx = Sy = Sxx = Syy = Sxy = 0.0
    for x, y in zip(X, Y):
        Sx = Sx + x
        Sy = Sy + y
        Sxx = Sxx + x*x
        Syy = Syy + y*y
        Sxy = Sxy + x*y
    det = Sxx * N - Sx * Sx
    return (Sxy * N - Sy * Sx)/det, (Sxx * Sy - Sx * Sxy)/det


x = [12, 34, 29, 38, 34, 51, 29, 34, 47, 34, 55, 94, 68, 81]
a,b = linreg(range(len(x)),x)  //your x,y are switched from standard notation
Run Code Online (Sandbox Code Playgroud)

趋势线不太可能通过原始点,但它将尽可能接近直线可以得到的原始点.使用此趋势线(a,b)的渐变和截距值,您将能够推断超出数组末尾的线:

extrapolatedtrendline=[a*index + b for index in range(20)] //replace 20 with desired trend length
Run Code Online (Sandbox Code Playgroud)


Abh*_*jit 18

Keith提供的链接或者Riaz的回答可能会帮助你获得多重拟合,但是如果可用的话,总是建议使用库,对于你手中的问题,numpy提供了一个很棒的多项式拟合函数叫做polyfit.您可以使用polyfit来拟合任何等式的数据.

下面是一个使用numpy将数据拟合为y = ax + b形式的线性方程的示例

>>> data = [12, 34, 29, 38, 34, 51, 29, 34, 47, 34, 55, 94, 68, 81]
>>> x = np.arange(0,len(data))
>>> y=np.array(data)
>>> z = np.polyfit(x,y,1)
>>> print "{0}x + {1}".format(*z)
4.32527472527x + 17.6
>>> 
Run Code Online (Sandbox Code Playgroud)

类似地,二次拟合也是如此

>>> print "{0}x^2 + {1}x + {2}".format(*z)
0.311126373626x^2 + 0.280631868132x + 25.6892857143
>>> 
Run Code Online (Sandbox Code Playgroud)


Kei*_*all 6

您可以对数据进行最小二乘拟合.

使用此页面中的公式:

y = [12, 34, 29, 38, 34, 51, 29, 34, 47, 34, 55, 94, 68, 81]
N = len(y)
x = range(N)
B = (sum(x[i] * y[i] for i in xrange(N)) - 1./N*sum(x)*sum(y)) / (sum(x[i]**2 for i in xrange(N)) - 1./N*sum(x)**2)
A = 1.*sum(y)/N - B * 1.*sum(x)/N
print "%f + %f * x" % (A, B)
Run Code Online (Sandbox Code Playgroud)

其中打印最佳拟合线的起始值和增量.

  • 尽管如此,做一个拟合需要您事先知道功能形式("趋势").除非你想猜测并检查随机函数,但所有可能函数的空间都是无限的,所以你无法知道你是否正确. (2认同)
  • @KeithRandall,这是一个强有力的假设,但不一定是真的。 (2认同)

And*_*ark 5

这是获得上升/下降趋势的一种方法:

>>> x = [12, 34, 29, 38, 34, 51, 29, 34, 47, 34, 55, 94, 68, 81]
>>> trend = [b - a for a, b in zip(x[::1], x[1::1])]
>>> trend
[22, -5, 9, -4, 17, -22, 5, 13, -13, 21, 39, -26, 13]
Run Code Online (Sandbox Code Playgroud)

在结果列表中trendtrend[0]可以理解为从增加x[0]x[1]trend[1]将是从增加x[1]x[2]等负值中trend平均这个值在x从一个指数下降到下一个。