28.02

2014

Linia trendu z MS Excel w R

Autor: artur

1 Wstęp

Dopasowanie linii trendu w Excelu jest najczęstszym sposobem na analizę zależności dwóch wielkości lub na prognozę zjawiska zależnego od czasu. Oczywiście, istnieją są znacznie lepsze metody, ale to podejście jest bardzo wygodne ze względu na możliwość ,,wyklikania” linii trendu. Przykładem bardziej zaawansowanych metod są narzędzia analizy i prognozowania szeregów czasowych.

Dlaczego czasami warto dopasowywać trend w R, a nie w Excelu? Jest kilka możliwych powodów:

  • jeśli chcemy dopasować trendy dla wielu zależności, to w R automatyzacja będzie dużo łatwiejsza,
  • gdy chcemy przetestować więcej rodzajów modeli (równań), to w R będzie łatwiej,
  • możemy też wybrać praktycznie dowolne modele, a nie tylko z listy gotowych.

Przyglądając się dokładniej metodom stosowanym w Excelu, okazuje się, że tak naprawdę wewnątrz nie dzieje się nic szczególnego: dopasowując trendy różnych rodzajów Excel kolejno:

  • przekształca odpowiednio (w sposób nieliniowy) dane,
  • dopasowuje do tych przekształconych danych model regresji liniowej z wykorzystaniem metody najmniejszych kwadratów.

Podejścia, na których bazujemy dopasowując trendy w R to regresja liniowa i regresja nieliniowa. Nie będziemy jednak wchodzić w szczegóły matematyczne ponieważ tekst jest skierowany do praktyków. Nawet jeśli będzie to kosztem rażących dla matematyków uproszczeń ;-)

Dopasowanie trendu w R wymaga wykonania kilku dodatkowych operacji, co oznacza, że początkowo będzie to trudniejsze niż w Excelu. Można jednak ,,spakować” te operacje w wygodne w użyciu funkcje. Wtedy praca z R staje się prawie tak samo wygodna. Warto zainwestować, ponieważ dzięki pracy z R uzyskujemy większą elastyczność i możliwości automatyzacji.

Po przeczytaniu tego artykułu będziesz umieć dopasowywać linie trendu w R oraz wykonywać prognozy. Tak, jak to w tej chwili robisz w Excelu.

2 Przygotowanie danych do analizy

Mamy dane, zmierzone w odstępach czasowych. Zainteresowany czytelnik może oczywiście wygenerować ciekawsze dane lub wczytać własne. Żeby mieć wygodną interpretację, załóżmy, że jest to wartość sprzedaży pewnego produktu w kolejnych miesiącach:

time <- 1:8
sales <- c(11, 12, 17.5, 19.7, 21.3, 24.5, 28.5, 30)

Przyjrzyjmy się tym danym:

plot(time, sales)
Wykres danych do eksperymentów

Wykres danych do eksperymentów

3 Model liniowy

Zacznijmy od najprostszego trendu liniowego (czyli regresji liniowej).

3.1 Dwa warianty

W Excelu możemy zaznaczyć jedną kolumnę (tylko wartości Y — zmiennej zależnej albo prognozowanej) albo dwie kolumny (wartości X — zmiennej niezależnej, od której zależy prognoza oraz Y). W pierwszym wariancie stosowana w modelowaniu zmienna X będzie automatycznie przyjmowała wartości od 1 do liczby elementów w zakresie Y.

W przypadku R musimy pamiętać o tym, żeby w obu przypadkach wprost podać obie zmienne.

3.2 Dopasowanie modelu

Teraz zbudujmy model liniowy. Trafi on do zmiennej model i możemy z niego później skorzystać.

(model <- lm(sales ~ time))
## 
## Call:
## lm(formula = sales ~ time)
## 
## Coefficients:
## (Intercept)         time  
##        7.81         2.83

Jeśli zmienne będą w ramce danych, zamiast ,,luzem” w przestrzeni roboczej, to postępujemy podobnie:

d <- data.frame(time, sales)
model <- lm(sales ~ time, d)

3.3 Ilustracja

Zobaczmy, jak wygląda dopasowanie modelu do danych:

plot(d$time, d$sales, pch = 20, cex = 1.5)
abline(model, col = "red", lwd = 2)
Dopasowanie modelu do danych

Dopasowanie modelu do danych

3.4 Ocena jakości dopasowania

Współczynnik R^2 (R-squared, nie adjusted R-squared) dostępny z Excela opisuje jakość dopasowania. Można wydostać go z dopasowanego w R modelu w taki sposób:

summary(model)$r.squared
## [1] 0.9838

Możliwe jest wobec tego pokazanie współczynnika R^2 na wykresie.

plot(d$time, d$sales)
abline(model)
text(mean(d$time), mean(d$sales), round(summary(model)$r.squared, 3), pos = 4)
Dodatkowo pokazujemy współczynnik R^2 na wykresie

Dodatkowo pokazujemy współczynnik R^2 na wykresie

3.5 Równanie na wykresie

Podejrzyjmy najpierw współczynniki modelu:

model$coefficients  # lub krócej: coef(model)
## (Intercept)        time 
##       7.807       2.835

Oczywiście, ponieważ w R można na wykresach wyświetlać wzory matematyczne, możliwe jest też wyświetlenie eleganckiego równania modelu (jak w Excelu). Na przykład w taki sposób:

plot(d$time, d$sales)
abline(model)
model.coef <- round(coef(model), 3)
mtext(bquote(y == .(model.coef[2]) * x + .(model.coef[1])), adj = 1, padj = 0)
Dodajemy równanie trendu

Dodajemy równanie trendu

3.6 Prognoza

Aby wykonać prognozę należy przygotować ramkę danych, w której będą odpowiednie wartości dla zmiennej time

time.pred <- 9:12  # prognozujemy na kolejne 4 miesiące
sales.pred <- predict(model, data.frame(time = time.pred))
 
d.pred <- data.frame(time = time.pred, sales = sales.pred)

Oto sposób, jak dokleić prognozę do oryginalnych danych oraz pokazać prognozowane z modelu wartości wraz z danymi historycznymi, na których zbudowaliśmy model:

d.2 <- rbind(d, d.pred)
plot(d.2$time, d.2$sales)
Wartości historyczne i prognozowane

Wartości historyczne i prognozowane

3.7 Usprawnienie pracy I: trend liniowy jak w Excelu

Najwygodniej jest przygotować funkcję, która wszystko zrobi za nas. Prosta wersja tej funkcji może wyglądać tak:

add.linear.trend <- function(x, y, x.pred) {
    model <- lm(y ~ x)
 
    y.pred <- predict(model, data.frame(x = x.pred))
 
    plot(x, y, xlim = range(c(x, x.pred)), ylim = range(c(y, y.pred)), pch = 20, 
        cex = 1.5)
    abline(model, col = "red", lwd = 1.5)
    points(x.pred, y.pred, pch = 1, cex = 1.5)
 
    list(coefs = coef(model), r.squared = summary(model)$r.squared, y.y.pred = c(y, 
        y.pred))
}

Parametry funkcji:

  • x, y — wartości zmiennej
  • x.pred — wartości zmiennej x, dla których chcemy wykonać prognozę

W wyniku dostajemy:

  • listę, w której są:
  • współczynniki modelu,
  • współczynnik R^2,
  • prognozowane wartości doklejone do oryginalnych danych (w postaci ramki danych),
  • prosty rysunek (do udoskonalenia — dla chętnych).

I takie rozwiązanie jest już prawie tak wygodne, jak linia trendu z Excela. Funkcji używa się bardzo prosto:

add.linear.trend(time, sales, 9:12)
Dane i trend narysowane z wykorzystaniem napisanej funkcji

Dane i trend narysowane z wykorzystaniem napisanej funkcji

## $coefs
## (Intercept)           x 
##       7.807       2.835 
## 
## $r.squared
## [1] 0.9838
## 
## $y.y.pred
##                                                     1     2     3     4 
## 11.00 12.00 17.50 19.70 21.30 24.50 28.50 30.00 33.32 36.15 38.99 41.82

W wyniku otrzymujemy wszystkie potrzebne informacje i możemy je przechować w dodatkowej zmiennej:

linear.trend <- add.linear.trend(time, sales, 9:12)

4 Rodzaje modeli dla trendu w Excelu

Tutaj pokażemy, jak opisać w R modele znane z Excela (na przykładzie wielkości xy, gdzie y jest prognozowana zależnie od x):

  • liniowy,
  • wielomianowy,
  • potęgowy,
  • logarytmiczny,
  • wykładniczy,
  • ruchoma średnia.

Wzory dla modeli i sposoby przygotowania danych dla tych modeli pokażemy później.

Excel udostępnia także wśród trendów ruchomą średnią (moving average). Ten rodzaj trendu bazuje na innym podejściu. Wobec tego zajmiemy się nim innym razem.

W R można dopasować także dowolny inny trend: wystarczy napisać odpowiednią formułę. Mimo, że w tym przypadku zastosowane są najbardziej zaawansowane metody matematyczne, zaczniemy od tego przypadku ponieważ zapis jest najbardziej intuicyjny.

5 Przykładowy model nieliniowy

Prostym i intuicyjnym sposobem na zbudowanie modelu nieliniowego jest wykorzystanie formuły, która go wprost opisuje.

W tym przypadku pokażemy tylko fragmenty kompletnej procedury. Połączenie ich w całość przebiega podobnie, jak w przypadku modelu liniowego pokazanego wyżej. Użyjemy funkcji nls() na przykładzie modelu stopnia drugiego. Oznacza to, że do naszych danych dopasowujemy parabolę.

(model.2 <- nls(sales ~ a + b * time^2 + c * time, d, start = list(a = 0, b = 1, 
    c = 1)))
## Nonlinear regression model
##   model: sales ~ a + b * time^2 + c * time
##    data: d
##       a       b       c 
##  7.4946 -0.0208  3.0220 
##  residual sum-of-squares: 5.48
## 
## Number of iterations to convergence: 1 
## Achieved convergence tolerance: 2.29e-07

W tym przypadku można wykorzystać całkiem dowolną formułę, nawet niezbyt sensowną sales ~ a * sin(b * time) + c * cos(d * time). Metoda znalezienia współczynników jest uniwersalna i nie wykorzystuje żadnych szczególnych właściwości użytej formuły. Można powiedzieć, że metoda ,,nie wie”, że dopasowuje model kwadratowy.

Niestety, takie rozwiązanie wymaga podania wartości początkowych. To jest często trudne zadanie i w praktyce nie jest wygodne. Pozwala jednak na dopasowanie dowolnych funkcji, a nie tylko takich, które można sprowadzić do zależności liniowych poprzez przekształcenie danych.

6 Model nieliniowy — zbudowany jako model liniowy na nieliniowo przekształconych danych

Drugie podejście polega na odpowiednim przekształceniu danych oraz zastosowaniu modelu liniowego.

Pokażemy to na prostym przykładzie — modelu drugiego stopnia. Jeśli chcielibyśmy dopasować taki model, to przed wykorzystaniem regresji liniowej można przekształcić dane na dwa sposoby:

  • w danych — wymagane są operacje na danych — niezbyt wygodne
  • w formule — korzystając ze specjalnych wyrażeń — najlepsze z tych rozwiązań

6.1 Przekształcenie w danych

W tym wariancie musimy dodać do danych dodatkową kolumnę. Jeśli model byłby wyższego stopnia niż 2, to wtedy potrzeba więcej dodatkowych kolumn.

d.2 <- d
d.2$time.2 <- d.2$time^2
 
(model <- lm(sales ~ time.2 + time, d.2))
## 
## Call:
## lm(formula = sales ~ time.2 + time, data = d.2)
## 
## Coefficients:
## (Intercept)       time.2         time  
##      7.4946      -0.0208       3.0220

6.2 Przekształcenie w formule

Tutaj korzystamy ze specjalnego zapisu formuły, gdzie I(.) oznacza, że mamy wykonać operację arytmetyczną na zmiennej:

(model <- lm(sales ~ I(time^2) + time, d))
## 
## Call:
## lm(formula = sales ~ I(time^2) + time, data = d)
## 
## Coefficients:
## (Intercept)    I(time^2)         time  
##      7.4946      -0.0208       3.0220

6.3 Porównanie

Porównajmy współczynniki dla wszystkich trzech sposobów budowy modeli. Okazuje się, że są praktycznie takie same.

7 Sposób przekształcenia danych dla poszczególnych rodzajów modeli

Teraz przejrzymy kolejne funkcje w Excelu i pokażemy, jak w poszczególnych przypadkach przekształcić dane, żeby móc dopasować model liniowy. W Excelu mamy dostępne takie funkcje (podajemy kolejno: nazwę, wzór na model, opis sposobu przekształcenia oraz formułę wykorzystującą funkcję dopasowującą model liniowy LINEST, która pokazuje sposób przekształcenia danych).

Rodzaj trendu Wzór trendu Opis przekształcenia Komentarz Funkcja Excela
liniowa (linear) $y = a_0 + a_1 x$ bez przekształcenia LINEST(y, x)
wielomian (polynomial) $y = a_0 + a_1 x^1 + a_2 x^2 + \ldots + a_{n-1} x^{n-1} + a_n x^n}$ przekształcenie danych przez podnoszenie do kolejnych potęg LINEST(Y, X^{1, 2, 3, ..., n})
potęgowa (power) $y = a x^b$ obustronne zlogarytmowanie uwaga: wartości $<= 0$ są niedopuszczalne LINEST( LN(Y), LN(X))
logarytmiczna (logarithmic) $y = a + b ln(x)$ zlogarytmowanie x LINEST(Y, LN(X))
wykładnicza (exponential) $y = a b^x$ logarytmujemy y uwaga: wartości $<= 0$ są niedopuszczalne LINEST(LN(Y), X)

8 Przykład przekształcenia danych — trend logarytmiczny

Na przykładzie trendu wykładniczego łatwo widać, jak w praktyce wykonać przekształcenia danych wymienione wyżej:

lm(sales ~ log(time))

9 Usprawnienie pracy II: funkcje przekształcające dane i dopasowujące modele dla poszczególnych rodzajów trendów

Jeśli dużo pracujemy z trendami, to wygodnie napisać sobie pakiet funkcji, które będą dopasowywać trendy poszczególnych rodzajów oraz wykonywać odpowiednie prognozy. Przyjrzyjmy się przykładowi na dla trendu logarytmicznego.

log.trend.fit <- function(x, y) {
    lm(y ~ log(x))
}
log.trend.predict <- function(model, x) {
    coef(model)[2] * log(x) + coef(model)[1]
}

Oczywiście, każdą z takich funkcji można przygotować tak, jak funkcja dla trendu liniowego: uzupełnić o rysowanie wykresu i zwracanie odpowiednich wyników.

Spójrzmy teraz, jak używa się takich funkcji. W tym celu przygotujemy proste dane:

# dane
x <- 1:9
y <- 2 * x + rnorm(9)
 
plot(x, y)
Proste dane do eksperymentów

Proste dane do eksperymentów

Zastosowanie funkcji jest już bardzo proste — prawie jak dodanie linii trendu w Excelu:

# okres prognozy
x.pred <- 10:15
 
log.trend.predict(log.trend.fit(x, y), x.pred)
## [1] 16.18 16.89 17.53 18.13 18.68 19.19

10 Odpowiedniki znanych z Excela funkcji do pracy z trendami

Na koniec dodatkowo tłumaczenie funkcji Excela na ich odpowiedniki w R. Może się przydać, jeśli w Excelu dopasowujesz trendy do danych także z wykorzystaniem formuł, a nie tylko klikając myszą.

Excel R Uwagi
LINEST lm(y ~ x)
INTERCEPT coefs(lm(y ~ x))[1]
SLOPE coefs(lm(y ~ x))[2]
TREND lm(y ~ x)
LOGEST lm(log(y) ~ x) tak naprawdę przekazuje parametry do LINEST
GROWTH lm(log(y) ~ log(x)) dla modelu exponential

Spróbuj ponownie