我正在尝试使用Numpy和Scipy找到最快速,最有效的斜率计算方法。我有一个包含三个Y变量和一个X变量的数据集,我需要计算它们各自的斜率。例如,我可以轻松地一次执行这一行,如下所示,但我希望有一种更有效的方法。我也不认为linregress是最好的方法,因为我的结果中不需要任何辅助变量,如拦截,标准错误等。任何帮助是极大的赞赏。
import numpy as np
from scipy import stats
Y = [[ 2.62710000e+11 3.14454000e+11 3.63609000e+11 4.03196000e+11
4.21725000e+11 2.86698000e+11 3.32909000e+11 4.01480000e+11
4.21215000e+11 4.81202000e+11]
[ 3.11612352e+03 3.65968334e+03 4.15442691e+03 4.52470938e+03
4.65011423e+03 3.10707392e+03 3.54692896e+03 4.20656404e+03
4.34233412e+03 4.88462501e+03]
[ 2.21536396e+01 2.59098311e+01 2.97401268e+01 3.04784552e+01
3.13667639e+01 2.76377113e+01 3.27846013e+01 3.73223417e+01
3.51249997e+01 4.42563658e+01]]
X = [ 1990. 1991. 1992. 1993. 1994. 1995. 1996. 1997. 1998. 1999.]
slope_0, intercept, r_value, p_value, std_err = stats.linregress(X, Y[0,:])
slope_1, intercept, r_value, p_value, std_err = stats.linregress(X, Y[1,:])
slope_2, intercept, r_value, p_value, std_err = stats.linregress(X, Y[2,:])
slope_0 = slope/Y[0,:][0]
slope_1 = slope/Y[1,:][0]
slope_2 = slope/Y[2,:][0]
b, a = polyfit(X, Y[1,:], 1)
slope_1_a = b/Y[1,:][0]
答案 0 :(得分:20)
最快最有效的方法是使用来自linregress的本地scipy函数来计算所有内容:
斜率:回归线的斜率
拦截:回归线的拦截
r值:相关系数
p值:假设检验的双边p值,其零假设是斜率为零
stderr:估算的标准误差
这是一个例子:
a = [15, 12, 8, 8, 7, 7, 7, 6, 5, 3]
b = [10, 25, 17, 11, 13, 17, 20, 13, 9, 15]
from scipy.stats import linregress
linregress(a, b)
会回复你:
LinregressResult(slope=0.20833333333333337, intercept=13.375, rvalue=0.14499815458068521, pvalue=0.68940144811669501, stderr=0.50261704627083648)
P.S。只是斜率的数学公式:
答案 1 :(得分:5)
线性回归计算在一个维度上是vector calculation。这意味着我们可以在整个 Y 矩阵上组合乘法,然后使用numpy中的 axis 参数对拟合进行矢量化。在你的情况下,适用于以下
((X*Y).mean(axis=1) - X.mean()*Y.mean(axis=1)) / ((X**2).mean() - (X.mean())**2)
您对合适的质量参数不感兴趣,但大多数参数可以类似的方式获得。
答案 2 :(得分:4)
比接受的答案更简单的表示:
x = np.linspace(0, 10, 11)
y = np.linspace(0, 20, 11)
y = np.c_[y, y,y]
X = x - x.mean()
Y = y - y.mean()
slope = (X.dot(Y)) / (X.dot(X))
斜率的等式来自Vector notation for the slope of a line using simple regression。
答案 3 :(得分:1)
X和Y的定义方式与您的问题相同,您可以使用:
dY = (numpy.roll(Y, -1, axis=1) - Y)[:,:-1]
dX = (numpy.roll(X, -1, axis=0) - X)[:-1]
slopes = dY/dX
numpy.roll()帮助您将下一个观察与当前观察对齐,您只需要删除最后一列,这是最后一次和第一次观察之间无用的区别。然后你可以一次计算所有的斜率,而不是scipy。
在您的示例中,dX
始终为1,因此您可以通过计算slopes = dY
来节省更多时间。
答案 4 :(得分:1)
我的方法是使用np.diff()函数:
dx = np.diff(xvals),
dy = np.diff(yvals)
坡度= dy / dx
答案 5 :(得分:1)
如前所述,您可以使用scipy的linregress。以下是解决坡度的方法:
from scipy.stats import linregress
x=[1,2,3,4,5]
y=[2,3,8,9,22]
slope, intercept, r_value, p_value, std_err = linregress(x, y)
print(slope)
请记住,以这种方式进行操作,因为您正在计算r_value和p_value之类的额外值,因此比手动计算斜率需要更长的时间。但是,Linregress很快。
来源:https://docs.scipy.org/doc/scipy/reference/generated/scipy.stats.linregress.html
答案 6 :(得分:0)
我在其他答案和原始回归公式的基础上构建了适用于任何张量的函数。
它将计算沿给定轴的数据斜率。因此,如果您具有任意张量X[i,j,k,l], Y[i,j,k,l]
,并且想知道沿着第三轴数据的所有其他轴的斜率,则可以使用calcSlopes( X, Y, axis = 2 )
来调用它。
import numpy as np
def calcSlopes( x = None, y = None, axis = -1 ):
assert x is not None or y is not None
# assume that the given single data argument are equally
# spaced y-values (like in numpy plot command)
if y is None:
y = x
x = None
# move axis we wanna calc the slopes of to first
# as is necessary for subtraction of the means
# note that the axis 'vanishes' anyways, so we don't need to swap it back
y = np.swapaxes( y, axis, 0 )
if x is not None:
x = np.swapaxes( x, axis, 0 )
# https://en.wikipedia.org/wiki/Simple_linear_regression
# beta = sum_i ( X_i - <X> ) ( Y_i - <Y> ) / ( sum_i ( X_i - <X> )^2 )
if x is None:
# axis with values to reduce must be trailing for broadcast_to,
# therefore transpose
x = np.broadcast_to( np.arange( y.shape[0] ), y.T.shape ).T
x = x - ( x.shape[0] - 1 ) / 2. # mean of (0,1,...,n-1) is n*(n-1)/2/n
else:
x = x - np.mean( x, axis = 0 )
y = y - np.mean( y, axis = 0 )
# beta = sum_i x_i y_i / sum_i x_i*^2
slopes = np.sum( np.multiply( x, y ), axis = 0 ) / np.sum( x**2, axis = 0 )
return slopes
它也有the俩,只能处理等距的y数据。例如:
y = np.array( [
[ 1, 2, 3, 4 ],
[ 2, 4, 6, 8 ]
] )
print( calcSlopes( y, axis = 0 ) )
print( calcSlopes( y, axis = 1 ) )
x = np.array( [
[ 0, 2, 4, 6 ],
[ 0, 4, 8, 12 ]
] )
print( calcSlopes( x, y, axis = 1 ) )
输出:
[1. 2. 3. 4.]
[1. 2.]
[0.5 0.5]
答案 7 :(得分:0)
这种清晰的单线飞机应该足够有效,而且不会发臭:
slope = np.polyfit(X,Y,1)[0]
最后你应该得到
import numpy as np
Y = np.array([
[ 2.62710000e+11, 3.14454000e+11, 3.63609000e+11, 4.03196000e+11, 4.21725000e+11, 2.86698000e+11, 3.32909000e+11, 4.01480000e+11, 4.21215000e+11, 4.81202000e+11],
[ 3.11612352e+03, 3.65968334e+03, 4.15442691e+03, 4.52470938e+03, 4.65011423e+03, 3.10707392e+03, 3.54692896e+03, 4.20656404e+03, 4.34233412e+03, 4.88462501e+03],
[ 2.21536396e+01, 2.59098311e+01, 2.97401268e+01, 3.04784552e+01, 3.13667639e+01, 2.76377113e+01, 3.27846013e+01, 3.73223417e+01, 3.51249997e+01, 4.42563658e+01]]).T
X = [ 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999]
print np.polyfit(X,Y,1)[0]
输出为[1.54983152e + 10 9.98749876e + 01 1.84564349e + 00]
答案 8 :(得分:0)
好吧,这取决于您拥有的分数。如果有两点,请从linregress
的{{1}}中选择stats
。如果更多,请使用scipy
,因为它避免了数据中多达29%的异常值并计算出最佳斜率。前者仅考虑所有样本,而不用担心异常值,而是计算适合所有样本的最佳斜率。
theilslope
答案 9 :(得分:0)