26.03

2014

Dodatkowa oś Y na wykresach w pakiecie R

Autor: adam

Często, kiedy analizujemy dane, potrzebne jest proste pokazanie zależności pomiędzy dwiema zmiennymi, rejestrowanymi w różnych jednostkach (skalach). Przykładem może być analiza zależności zużycia energii elektrycznej (w MW) od temperatury (w stopniach Celsjusza) lub badanie związku pomiędzy stopą bezrobocia (w %) a wartością PKB (w mld. dolarów) w kolejnych okresach.

W takim przypadku pomocne byłoby przedstawienie dwóch serii danych na jednym wykresie. W arkuszach Excel lub Calc taką dodatkową oś Y bardzo prosto możemy dodać do wykresu wykorzystując opcję: Formatuj serie danych -> Pomocnicza oś Y (patrz Rysunek 1). W środowisku R nie jest już jednak tak prosto. Dlatego dzisiaj postanowiłem przyjrzeć się temu, jak można skonstruować podobny wykres (z dwiema osiami Y), wykorzystując narzędzia dostępne w R.

1 Po co dwie osie Y na jednym wykresie?

Na początek, wymieńmy typowe sytuacje, w których stosowanie dodatkowej osi Y na wykresie może być przydatne.

  • Dodanie drugiej osi Y umożliwia przedstawienie danych z zastosowaniem dwóch różnych skal pomiarowych jednocześnie. Jest to szczególnie przydatne w przypadku wykresów mieszanych (np. kolumnowo-liniowych), które pokazują dwie serie danych.
  • Zastosowanie osobnych skal dla każdej serii danych zwiększa przejrzystość wykresu i ułatwia jego interpretację!
  • Możemy łatwo porównać zależności pomiędzy dwiema zmiennymi. Przykład: wielkość sprzedaży (w tys. sztuk) i cena produktu (w PLN) w kolejnych miesiącach roku.
  • Możemy porównać dwa różne kryteria oceny dokładności modelu dla różnych parametrów/scenariuszy. Przykład: porówanie dokładności prognoz z wykorzystaniem kryterium błędu procentowego (np. MAPE) i błędu średniokwadratowego (RMSE) dla różnych metod prognozowania.

2 Przykładowe dane

  • Typową sytuacją, kiedy chcielibyśmy porównać dwie wielkości (rejestrowane w różnych jednostkach) jest analiza wielkości sprzedaży (w tys sztuk) w powiązaniu z ceną produktu (w PLN).
  • Przykład takich danych przedstawia Rys.1, na którym widać także skonstruowany w arkuszu Calc wykres słupkowy-liniowy, zawierający pomocniczą oś Y.
Rysunek 1: Przykładowe dane: Cena produktu vs. wielkość sprzedaży. Wykres w arkuszu Calc.

Rysunek 1: Przykładowe dane: Cena produktu vs. wielkość sprzedaży. Wykres w arkuszu Calc.

  • Spróbujmy skonstruować podobny wykres w pakiecie R.
  • Zaczynamy od wczytania danych (zmienne CENA i SPRZEDAZ, dla kolejnych miesięcy: I, II, …, XII).
  • W pierwszym kroku, przedstawimy nasze dane na dwóch osobnych wykresach, tzn. wykres słupkowy dla ceny produktu i wykres liniowy dla wielkości sprzedaży w kolejnych okresach.
cena <- c(14.5, 13.5, 13.2, 13.1, 13.7, 14.1, 14.8, 15.1, 15.2, 15, 14.7, 14.9)
sprzedaz <- c(20025, 16125, 17424, 17161, 18769, 19881, 21904, 21801, 22104, 
    22500, 22300, 23112)
 
par(mfrow = c(2, 1))
 
# Wykres slupkowy: SPRZEDAZ
barplot(sprzedaz, col = "lightblue", xlab = "miesiace", ylab = "SPRZEDAZ [tys. sztuk]", 
    main = "Sprzedaz", names.arg = as.roman(1:12), ylim = c(15000, 25000), xpd = FALSE)
# Wykres liniowy: CENA
plot(cena, col = "red", pch = 16, cex = 1.5, type = "b", main = "Cena", xlab = "miesiace", 
    ylab = "CENA [pln]")
Rysunek 2: Wykres danych

Rysunek 2: Wykres danych

  • Oczywiście dwa osobne wykresy dają pewien pogląd na zależność pomiędzy ceną a wielkością sprzedaży w kolejnych miesiącach.
  • Wygodniejsze byłoby jednak przedstawienie obu tych zmiennych na jednym wykresie…

3 Pomocnicza oś Y — standardowa metoda

  • Zacznijmy od standardowej metody wykorzystującej opcję par(new=TRUE), która powoduje, że poprzedni wykres nie będzie czyszczony, gdy wywołamy kolejną graficzną funkcję wysokiego poziomu (np. plot(...)).
# zwiekszamy margines
old.mar <- par("mar")
par(mar = old.mar + c(0, 0, 0, 2))
 
# 1) Wykres slupkowy (SPRZEDAZ)
barplot.xticks <- barplot(sprzedaz, col = "lightblue", xlim = c(0, 14), ylim = c(15000, 
    25000), xlab = "miesiace", ylab = "SPRZEDAZ [tys. sztuk]", xpd = FALSE, 
    axes = FALSE)
box()
axis(1, at = barplot.xticks, labels = as.roman(1:12))
axis(2, at = seq(from = 15000, to = 25000, by = 2500), col = "lightblue", lwd = 2)
 
# 2) Wykres liniowy (CENA) + pomocnicza os Y
par(new = TRUE)
plot(barplot.xticks, cena, type = "b", lwd = 2, col = "red", pch = 16, cex = 1.5, 
    xlab = "", ann = FALSE, axes = FALSE, xlim = c(0, 14), ylim = c(13, 16), 
    yaxs = "i")
# dodatkowa os Y
axis(4, col = "red", at = seq(from = 13, to = 16, by = 0.5), lwd = 2)
mtext("CENA [pln]", side = 4, line = 3)
 
title("Sprzedaz vs. cena")
Rysunek 3: Pomocnicza oś Y na wykresie -- metoda standardowa

Rysunek 3: Pomocnicza oś Y na wykresie — metoda standardowa

3.1 Uwagi

  • Aby pozycje punktów na wykresie liniowym odpowiadały środkom słupków wykorzystujemy zmienną barplot.xticks (wynik funkcji barplot)
  • Opcja yaxs = "i" zmienia standardowy styl rysowania osi (regular) na internal, dzięki czemu zakres osi Y będzie zgodny z wartością określoną przez ylim (zakres danych nie będzie dodatkowo rozszerzany o 4%).
  • Aby dodać wykres liniowy do istniejącego wykresu słupkowego wykorzystaliśmy par(new=TRUE).
    Inna możliwość to modyfikacja współrzędnych obszaru rysunku za pomocą parametru usr i wykorzystanie funkcji niskiego poziomu lines(), tzn.:
usr.old <- par("usr")
par(usr = c(usr.old[1:2], 13, 16))
lines(barplot.xticks, cena, type = "b", lwd = 2, col = "red", pch = 16, cex = 1.5, 
    xlim = c(0, 14), ylim = c(13, 16))

4 Pomocnicza oś Y — wykorzystanie funkcji twoord.plot (pakiet plotrix)

  • Ciekawą alternatywą dla opisanej powyżej metody ”standardowej” może być funkcji twoord.plot(..) z pakietu plotrix, która została opracowana właśnie z myślą o tworzeniu wykresów dla dwóch serii danych.
  • Funkcja umożliwia także bardzo wygodną modyfikację najważniejszych parametrów (takich jak np. etykietki i kolory osi czy pozycje znaczników).
  • W razie potrzeby, można także określić komendę (parametr do.first), która będzie wykonana na samym początku (dzięki temu możemy np. zmienić tło i dodać siatkę do naszego wykresu).

Przykład wykorzystania funkcji dla naszych danych przedstawia poniższy kod:

library(plotrix)
 
twoord.plot(
  barplot.xticks, sprzedaz, barplot.xticks, cena, 
  lcol="lightblue", rcol="red",  # kolory dla obu osi Y
  type=c("bar","b"), # typ pierwszego i drugiego wykresu
  # etykietki osi X, oraz obu osi Y
  xlab="miesiace", ylab="SPRZEDAZ [tys. sztuk]", rylab="CENA [pln]",  
  rpch=16, lwd=3, cex=1.5, 
  # pozycje znacznikow (os X)
  xtickpos=barplot.xticks, xticklab=as.roman(1:12),                   
  # pozycje znacznikow (lewa os Y)
  lytickpos=seq(from=15000,to=25000,by=2500),                         
  # pozycje znacznikow (prawa os Y)
  rytickpos=seq(from=13,to=16,by=0.5),                                  
  # zakresy dla osi
  xlim=c(0.5,14),lylim=c(15000,25000),rylim=c(13,16),                 
  mar=c(5,4,4,5)+.1, axislab.cex=1.2,   
  main="Sprzedaz vs. cena", 
  # modyfikacja szerokosci slupkow
  halfwidth=0.4,                                                      
  # dodatkowe polecenie (dodanie siatki)
  do.first="plot_bg(col=&#039;azure2');grid(col='white',lty=1,12,6)")
Rysunek 4: Wykres z wykorzystaniem funkcji 'twoord.plot{plotrix}`

Rysunek 4: Wykres z wykorzystaniem funkcji ‚twoord.plot{plotrix}`

Spróbuj ponownie