Вычисление склонов в Numpy (или Scipy)

Я пытаюсь найти самый быстрый и эффективный способ вычисления наклонов с помощью 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]

Ответ 1

Расчет линейной регрессии в одном измерении векторный расчет. Это означает, что мы можем комбинировать умножения на всей матрице Y, а затем векторизовать подгонки, используя параметр оси в numpy. В вашем случае это будет выглядеть следующим образом

((X*Y).mean(axis=1) - X.mean()*Y.mean(axis=1)) / ((X**2).mean() - (X.mean())**2)

Вам не нужны параметры качества, но большинство из них можно получить аналогичным образом.

Ответ 2

Самый быстрый и эффективный способ - использовать встроенную функцию scipy из linregress, которая вычисляет все:

наклон: наклон линии регрессии

перехват: перехват линии регрессии

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. Просто математическая формула для наклона:

введите описание изображения здесь

Ответ 4

Я сделал это с помощью функции np.diff():

dx = np.diff(xvals),

dy = np.diff(yvals)

склоны = dy/dx

Ответ 5

Как было сказано ранее, вы можете использовать скудный 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

Если 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.

Ответ 7

Я опирался на другие ответы и оригинальную формулу регрессии, чтобы построить функцию, которая работает для любого тензора. Он рассчитает наклоны данных вдоль заданной оси. Итак, если у вас есть произвольные тензоры 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

У него также есть уловка для работы с данными с одинаково разнесенными данными. Так, например:

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]

Ответ 8

Этот понятный однострочный текст должен быть достаточно эффективным без скучного:

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]