Расчет уклонов в Numpy (или Scipy) - PullRequest
10 голосов
/ 02 марта 2012

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

Ответы [ 7 ]

22 голосов
/ 21 ноября 2015

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

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

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

Значение 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)

PS Просто математическая формула для наклона:

enter image description here

6 голосов
/ 08 мая 2018

Представление, которое проще принятого ответа:

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

Уравнение для наклона получается из Векторные обозначения для наклона линии с использованием простой регрессии .

6 голосов
/ 02 марта 2012

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

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

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

2 голосов
/ 03 июля 2018

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

dx = np.diff (xvals),

dy = np.diff (yvals)

склоны = dy / dx

1 голос
/ 13 июня 2019

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

    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

1 голос
/ 02 марта 2012

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

0 голосов
/ 16 июня 2019

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

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]
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...