37

次のように、Pythonで数字のリストを持っています。

x = [12, 34, 29, 38, 34, 51, 29, 34, 47, 34, 55, 94, 68, 81]

これらの数値の傾向を見つける最善の方法は何ですか? 次の数字がどうなるかを予測することには興味がありません。トレンドを比較できるように、多くの数字セットのトレンドを出力したいだけです。

編集:傾向とは、数字が増加しているか減少しているか、およびその割合を数値で表現したいということです。私はあまり数学に詳しくないので、おそらくこれには適切な名前があります!

編集 2:私が本当に欲しいのは、線形ベスト フィットの係数のようです。Pythonでこれを取得する最良の方法は何ですか?

4

7 に答える 7

30

おそらく、これらの数値をグラフにプロットし、それらを通る直線を見つけて、線と数値の間の全体的な距離が最小になることを意味しているのでしょうか? これは線形回帰と呼ばれます

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

トレンド ラインが元のポイントを通過する可能性は低いですが、直線が得られる元のポイントに可能な限り近くなります。この傾向線 (a、b) の勾配と切片の値を使用すると、配列の末尾を過ぎた線を推定できます。

extrapolatedtrendline=[a*index + b for index in range(20)] //replace 20 with desired trend length
于 2012-04-06T20:23:54.543 に答える
24

キースによって提供されたリンクまたはおそらく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
>>> 

同様に、2次近似は次のようになります。

>>> print "{0}x^2 + {1}x + {2}".format(*z)
0.311126373626x^2 + 0.280631868132x + 25.6892857143
>>> 
于 2012-04-06T20:33:10.607 に答える
7

増加/減少トレンドを取得する 1 つの方法を次に示します。

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

結果のリストtrendでは、は からへtrend[0]の増加として解釈でき、 からへの増加などになります。 の負の値は、あるインデックスから次のインデックスへの値の減少を意味します。x[0]x[1]trend[1]x[1]x[2]trendx

于 2012-04-06T20:04:57.517 に答える
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)

最適な線の開始値とデルタを出力します。

于 2012-04-06T19:59:11.890 に答える
4

私はキースに同意します。おそらく、線形最小二乗法を探していると思います(数値が一般的に増加しているか減少しているか、およびその割合だけを知りたい場合)。フィットの勾配は、それらがどの程度増加しているかを示します。線形最小二乗近似の視覚的表現が必要な場合は、Wolfram Alpha を試してください。

http://www.wolframalpha.com/input/?i=linear+fit+%5B12%2C+34%2C+29%2C+38%2C+34%2C+51%2C+29%2C+34%2C +47%2C+34%2C+55%2C+94%2C+68%2C+81%5D

更新: Python で線形回帰を実装する場合は、Mathworld の説明から始めることをお勧めします。

http://mathworld.wolfram.com/LeastSquaresFitting.html

これはアルゴリズムの非常に簡単な説明であり、実際にはそれ自体を記述します。特に、式 16 ~ 21、27、および 28 に細心の注意を払う必要があります。

アルゴリズムを自分で書いてみてください。問題がある場合は、別の質問を開く必要があります。

于 2012-04-06T20:06:02.807 に答える
2

numpy を使用して OLS 係数を見つけることができます。

import numpy as np

y = [12, 34, 29, 38, 34, 51, 29, 34, 47, 34, 55, 94, 68, 81]

x = []
x.append(range(len(y)))                 #Time variable
x.append([1 for ele in xrange(len(y))]) #This adds the intercept, use range in Python3

y = np.matrix(y).T
x = np.matrix(x).T

betas = ((x.T*x).I*x.T*y)

結果:

>>> betas
matrix([[  4.32527473],  #coefficient on the time variable
        [ 17.6       ]]) #coefficient on the intercept

傾向変数の係数は正であるため、変数の観測値は時間の経過とともに増加しています。

于 2012-04-06T22:27:04.093 に答える
-1

ベータ係数を計算します。

y = [12, 34, 29, 38, 34, 51, 29, 34, 47, 34, 55, 94, 68, 81]
x = range(1,len(y)+1)

def var(X):
    S = 0.0
    SS = 0.0
    for x in X:
        S += x
        SS += x*x
    xbar = S/float(len(X))
    return (SS - len(X) * xbar * xbar) / (len(X) -1.0)

def cov(X,Y):
    n = len(X)
    xbar = sum(X) / n
    ybar = sum(Y) / n
    return sum([(x-xbar)*(y-ybar) for x,y in zip(X,Y)])/(n-1)


def beta(x,y):
    return cov(x,y)/var(x)

print beta(x,y) #4.34285714286
于 2012-04-06T20:50:42.900 に答える