libreria - Python: encontrar una tendencia en un conjunto de números
python 3.6 math module (7)
¿Posiblemente quiere decir que desea trazar estos números en un gráfico y encontrar una línea recta a través de ellos donde se minimiza la distancia total entre la línea y los números? Esto se llama regresión lineal.
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
Es poco probable que la línea de tendencia pase a través de sus puntos originales, pero será lo más cercana posible a los puntos originales que puede obtener una línea recta. Usando los valores de gradiente e intercepción de esta línea de tendencia (a, b), podrá extrapolar la línea más allá del final de la matriz:
extrapolatedtrendline=[a*index + b for index in range(20)] //replace 20 with desired trend length
Tengo una lista de números en Python, como este:
x = [12, 34, 29, 38, 34, 51, 29, 34, 47, 34, 55, 94, 68, 81]
¿Cuál es la mejor manera de encontrar la tendencia en estos números? No estoy interesado en predecir cuál será el próximo número, solo quiero mostrar la tendencia de muchos conjuntos de números para poder comparar las tendencias.
Edición: por tendencia, quiero decir que me gustaría una representación numérica de si los números están aumentando o disminuyendo y a qué velocidad. No soy masivamente matemático, así que probablemente haya un nombre apropiado para esto.
Edición 2: Parece que lo que realmente quiero es el coeficiente del mejor ajuste lineal. ¿Cuál es la mejor manera de conseguir esto en Python?
Aquí hay una forma de obtener una tendencia creciente / decreciente:
>>> 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]
En la lista de trend
resultante, la trend[0]
se puede interpretar como el aumento de x[0]
a x[1]
, la trend[1]
sería el aumento de x[1]
a x[2]
etc. Valores negativos en trend
significa que el valor en x
disminuyó de un índice al siguiente.
Calcular el coeficiente beta.
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
El enlace proporcionado por Keith o probablemente la respuesta de Riaz podría ayudarlo a obtener el ajuste poli, pero siempre se recomienda usar bibliotecas si están disponibles, y para el problema en su mano, el numpy proporciona una maravillosa función de ajuste polinómico llamada polyfit . Puede usar polyfit para ajustar los datos sobre cualquier grado de ecuación.
Aquí hay un ejemplo que usa numpy para ajustar los datos en una ecuación lineal de la forma 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
>>>
similarmente un ajuste cuadrático sería
>>> print "{0}x^2 + {1}x + {2}".format(*z)
0.311126373626x^2 + 0.280631868132x + 25.6892857143
>>>
Estoy de acuerdo con Keith, creo que probablemente estés buscando un ajuste lineal de mínimos cuadrados (si lo único que quieres saber es si los números generalmente aumentan o disminuyen, y a qué velocidad). La pendiente del ajuste le dirá a qué velocidad están aumentando. Si desea una representación visual de un ajuste lineal de mínimos cuadrados, pruebe Wolfram Alpha:
Actualización: si desea implementar una regresión lineal en Python, le recomiendo comenzar con la explicación en Mathworld:
http://mathworld.wolfram.com/LeastSquaresFitting.html
Es una explicación muy sencilla del algoritmo, y prácticamente se escribe a sí mismo. En particular, debe prestar mucha atención a las ecuaciones 16-21, 27 y 28.
Intente escribir el algoritmo usted mismo, y si tiene problemas, debe abrir otra pregunta.
Podrías hacer un ajuste por mínimos cuadrados de los datos.
Usando la fórmula de esta página :
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)
Lo que imprime el valor inicial y el delta de la línea de mejor ajuste.
Puedes encontrar el coeficiente OLS usando numpy:
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
y = np.matrix(y).T
x = np.matrix(x).T
betas = (x.T*x).I*x.T*y)
Resultados:
>>> betas
matrix([[ 4.32527473], #coefficient on the time variable
[ 17.6 ]]) #coefficient on the intercept
Como el coeficiente de la variable de tendencia es positivo, las observaciones en su variable aumentan con el tiempo.