Jak ustawić pionowo dwa wykresy o tej samej skali x, ale innej skali Y w R?

9

Pozdrowienia,

Obecnie wykonuję następujące czynności w języku R:

require(zoo)
data <- read.csv(file="summary.csv",sep=",",head=TRUE)
cum  = zoo(data$dcomp, as.Date(data$date))
data = zoo(data$compressed, as.Date(data$date))
data <- aggregate(data, identity, tail, 1)
cum  <- aggregate(cum, identity, sum, 1)
days = seq(start(data), end(data), "day")
data2 = na.locf(merge(data, zoo(,days)))

plot(data2,xlab='',ylab='compressed bytes',col=rgb(0.18,0.34,0.55))
lines(cum,type="h",col=rgb(0,0.5,0))

Snip of summary.csv:

date,revision,file,lines,nclass,nattr,nrel,bytes,compressed,diff,dcomp
2007-07-25,16,model.xml,96,11,22,5,4035,991,0,0
2007-07-27,17,model.xml,115,16,26,6,4740,1056,53,777
2007-08-09,18,model.xml,106,16,26,7,4966,1136,47,761
2007-08-10,19,model.xml,106,16,26,7,4968,1150,4,202
2007-09-06,81,model.xml,111,16,26,7,5110,1167,13,258
...

Ostatnie dwa wiersze przedstawiają potrzebne informacje, a wynik przypomina: alternatywny tekst Niebieska linia to entropia w bajtach artefaktu, który mnie interesuje. Zielone linie reprezentują entropię zmian.

Teraz na tym wykresie działa dobrze, ponieważ nie ma ogromnej różnicy w skalach. Ale mam inne wykresy, na których zielone linie stają się tak małe, że nie widać.

Rozwiązanie, którego szukałem, obejmowało dwie rzeczy:

  1. Aby przenieść zielone pionowe linie na drugi wykres, tuż poniżej pierwszego, z własną osią y, ale wspólną osią x.
  2. Aby zapewnić skalę logarytmiczną, ponieważ bardziej interesuje mnie „wielkość” niż określone wartości.

Z góry dziękuję!

PS Jeśli ktoś może mi również powiedzieć, jak mogę umieścić „drobne tiki” w skali X w odniesieniu do miesięcy, doceniam :-) Jeśli są to zbyt wiele pytań do jednego postu, mogę je dalej podzielić.

Hugo Sereno Ferreira
źródło

Odpowiedzi:

15

Możesz użyć par(new=TRUE)do wykreślenia na tym samym wykresie przy użyciu dwóch różnych osi Y! To powinno również rozwiązać twój problem.

Następnie znajdziesz prosty przykład, który wykreśla dwie losowe zmienne normalne, jedną na średniej 0, drugą na średniej 100 (oba sd s = 1) na tym samym wykresie. Pierwszy na czerwono na lewej osi y, drugi na niebiesko na prawej osi y. Następnie dodaje się etykiety osi.

Proszę bardzo:

x <- 1:10
y1 <- rnorm(10)
y2 <- rnorm(10)+100

plot(x,y1,pch=0,type="b",col="red",yaxt="n",ylim=c(-8,2))
par(new=TRUE)
plot(x,y2,pch=1,type="b",col="blue",yaxt="n",ylim=c(98,105))

axis(side=2)
axis(side=4)

wygląda wtedy tak (pamiętaj czerwony na lewej osi, niebieski na prawej osi): alternatywny tekst

AKTUALIZACJA:
Na podstawie komentarzy stworzyłem zaktualizowaną wersję mojego wykresu. Teraz zagłębiam się nieco w funkcjonalność wykresu bazowego, używając par(mar=c(a,b,c,d))do stworzenia większego marginesu wokół wykresu (potrzebnego do etykiety prawej osi), mtextaby wyświetlić etykiety osi i zaawansowane użycie axisfunkcji:

x <- 1:100
y1 <- rnorm(100)
y2 <- rnorm(100)+100

par(mar=c(5,5,5,5))

plot(x,y1,pch=0,type="b",col="red",yaxt="n",ylim=c(-8,2),ylab="")
axis(side=2, at=c(-2,0,2))
mtext("red line", side = 2, line=2.5, at=0)

par(new=TRUE)
plot(x,y2,pch=1,type="b",col="blue",yaxt="n",ylim=c(98,108), ylab="")
axis(side=4, at=c(98,100,102), labels=c("98%","100%","102%"))
mtext("blue line", side=4, line=2.5, at=100)

alternatywny tekst

Jak widać, jest to całkiem proste. Możesz zdefiniować pozycję swoich danych ylimw plotfunkcji, a następnie użyć atw axisfunkcji, aby wybrać, które oś znacznika chcesz zobaczyć. Co więcej, można nawet dostarczyć etykiety dla kleszczy osi (bardzo przydatnych dla nominalnej oś x) poprzez labelsw axisfunkcji (wykonanej tutaj na prawej osi). Aby dodać etykiety osi, użyj mtextz atdo pozycjonowania pionowego ( linedo pozycjonowania poziomego).

Upewnij się, aby sprawdzić ?plot, ?par, ?axis, i ?mtextaby uzyskać więcej informacji.
Świetne zasoby internetowe to: Quick-R dla wykresów: 1 , 2 i 3 .

Henrik
źródło
To ciekawe, ale jak powiedzieć czytelnikowi, która skala odpowiada linii?
Hugo Sereno Ferreira
Spójrz na ten wykres: imgur.com/K8BCr.png Tam przedstawiamy etykiety osi Y i znaczniki tylko tam, gdzie odnoszą się do danych (tj. Dla lewej osi u góry wykresu, jako odpowiednie dane, i dla prawej osi u dołu wykresu, jako dane odpowiadające). Dodatkowo zastosowaliśmy różne kolory (jak w powyższym przykładzie) i typy linii i wyjaśniliśmy to w podpisie. Możesz także użyć wykresu liniowego po lewej stronie i wykresu słupkowego na prawej osi, aby rozróżnić wyraźniej.
Henrik
Podany przykład jest bardzo dobry ... Jak udało się przesunąć w pionie każdą oś?
Hugo Sereno Ferreira
2
Naprawdę dobry przykład. Jedynym problemem związanym z wykresem jest to, że obie nazwy zmiennych Y nakładają się. W tym przypadku chciałbyś jeden po lewej, a drugi po prawej (być może nawet w pozycji pionowej). Aby zmienić swój przykład z „naprawdę dobrego” na „doskonały”, możesz użyć funkcji mtext z R do tworzenia nazw zmiennych
Dave Kellen
@ Hugo @Dave: Zobacz moją aktualizację zawierającą oba komentarze.
Henrik
12

Myślę, że możesz dostać to, czego chcesz ggplot2. Korzystając z poniższego kodu, mogę utworzyć:

alternatywny tekst

Oczywiście rzeczy takie jak kolory linii można zmienić na dowolne. Na osi X określiłem linie główne w latach i linie pomocnicze w miesiącach.

require(ggplot2)
t = as.Date(0:1000, origin="2008-01-01")  
y1 = rexp(1001)
y2 = cumsum(y1)
df = data.frame(t=t, values=c(y2,y1), type=rep(c("Bytes", "Changes"), each=1001))

g = ggplot(data=df, aes(x=t, y=values)) +
  geom_line() +
  facet_grid(type ~ ., scales="free") +
  scale_y_continuous(trans="log10") +
  scale_x_date(major="years", minor="months") +
  ylab("Log values")
g
csgillespie
źródło
Próbowałem skonfigurować df = data.frame (t = dni, wartości = c (data2, cum), type = rep (c („Bajty”, „Zmiany”), każdy = 1001)), ale daje Błąd w rbind.zoo (...): indeksy nakładają się
Hugo Sereno Ferreira
To dlatego, że data2 i cum są obiektami zoo. Użyj as.vector (data2), aby uzyskać surowe wartości. Użyłem również 1001, ponieważ miałem 1001 obserwacji. Będziesz potrzebował czegoś innego.
csgillespie
Użytkownik Noob R tutaj: Błąd w ramce danych (t = dni, wartości = c (as.vector (data2), as.vector (cum)),: argumenty wskazują na różną liczbę wierszy: 1063, 1300, 2
Hugo Sereno Ferreira,
Wpisz „dni”, „dane2” i „cum”, aby przejrzeć swoje dane. Następnie spójrz na „długość (dni)” itp. Musisz dopasować punkty czasowe do wartości.
csgillespie