Wykreśl dwa wykresy na tym samym wykresie w R.

570

Chciałbym narysować y1 i y2 na tym samym wykresie.

x  <- seq(-2, 2, 0.05)
y1 <- pnorm(x)
y2 <- pnorm(x, 1, 1)
plot(x, y1, type = "l", col = "red")
plot(x, y2, type = "l", col = "green")

Ale kiedy robię to w ten sposób, nie są one kreślone razem na tej samej fabule.

W Matlabie można to zrobić hold on, ale czy ktoś wie, jak to zrobić w R?

Sandra Schlichting
źródło
3
Sprawdź ?curve. Zastosowanie add=TRUE.
izomorfizmy
Zobacz to pytanie, aby uzyskać bardziej szczegółowe odpowiedzi na ggplot2.
Axeman

Odpowiedzi:

617

lines()lub points()doda do istniejącego wykresu, ale nie utworzy nowego okna. Więc musisz to zrobić

plot(x,y1,type="l",col="red")
lines(x,y2,col="green")
bnaul
źródło
10
Dlaczego to nie działa w następującym prostym przykładzie? > plot (sin)> linie (cos) Błąd w as.double (y): nie można wymusić typu „wbudowany” w wektor typu „podwójny”
Frank
23
Łatwo to zobaczyć. W przypadku plot (sin) przekazujesz funkcję zamiast rzeczywistych danych. plot () wykryje to i z kolei użyj plot.function (), aby wykreślić twoją funkcję (przeczytaj więcej o wysyłce, aby dowiedzieć się więcej na ten temat). Jednak linie.funkcje () nie są zdefiniowane, więc linie () nie wiedzą, co zrobić z parametrem funkcji klasy. linie mogą obsługiwać tylko obiekty danych i szeregów czasowych klasy ts.
Soumendra,
27
@Frank to zrobić następująco: plot(sin); curve(cos, add=TRUE).
izomorfizmy
2
Jak korzystać z tego samego, jeśli x jest inny? Powiedzmy, że mam x1 i y1 dla jednego wykresu i dodaję kolejny wykres x2 i y2 na tym samym wykresie. Zarówno x1, jak i x2 mają ten sam zakres, ale różne wartości.
Kavipriya
1
Jest dokładnie tak samo: lines(x2,y2,...)zamiastlines(x,y2,...)
bnaul
219

Możesz także używać pari drukować na tym samym wykresie, ale na innej osi. Coś w następujący sposób:

plot( x, y1, type="l", col="red" )
par(new=TRUE)
plot( x, y2, type="l", col="green" )

Jeśli przeczytasz szczegółowo parw R, będziesz w stanie wygenerować naprawdę ciekawe wykresy. Kolejną książką do obejrzenia jest grafika R Paula Murrela.

Sam
źródło
3
Mój R daje mi błąd: Błąd w par (rys. (Nowy = PRAWDA)): nie można znaleźć funkcji „fig”
Alessandro Jacopson
5
Czy twoja metoda zachowuje właściwą skalę (oś y) dla dwóch wykresów?
Alessandro Jacopson,
1
@uvts_cvs Tak, zachowuje oryginalny wykres w toto.
Sam
10
Problem polega na tym, że przepisuje kilka elementów fabuły. Chciałbym dołączyć xlab="", ylab="", ...i kilka innych w drugim plot.
izomorfizmy
118

Przy konstruowaniu wykresów wielowarstwowych należy wziąć pod uwagę ggplotpakiet. Chodzi o to, aby stworzyć obiekt graficzny o podstawowej estetyce i stopniowo go ulepszać.

ggplotstyl wymaga spakowania danych data.frame.

# Data generation
x  <- seq(-2, 2, 0.05)
y1 <- pnorm(x)
y2 <- pnorm(x,1,1)
df <- data.frame(x,y1,y2)

Podstawowe rozwiązanie:

require(ggplot2)

ggplot(df, aes(x)) +                    # basic graphical object
  geom_line(aes(y=y1), colour="red") +  # first layer
  geom_line(aes(y=y2), colour="green")  # second layer

Tutaj + operatorsłuży do dodawania dodatkowych warstw do podstawowego obiektu.

Dzięki temu ggplotmasz dostęp do obiektu graficznego na każdym etapie kreślenia. Załóżmy, że zwykła konfiguracja krok po kroku może wyglądać następująco:

g <- ggplot(df, aes(x))
g <- g + geom_line(aes(y=y1), colour="red")
g <- g + geom_line(aes(y=y2), colour="green")
g

gtworzy fabułę i można ją zobaczyć na każdym etapie (po utworzeniu co najmniej jednej warstwy). Dalsze zaklęcia fabuły są również tworzone za pomocą stworzonego obiektu. Na przykład możemy dodać etykiety dla osi:

g <- g + ylab("Y") + xlab("X")
g

Finał gwygląda jak:

wprowadź opis zdjęcia tutaj

AKTUALIZACJA (08.11.2013):

Jak wskazano w komentarzach, ggplotfilozofia sugeruje wykorzystanie danych w długim formacie. Możesz odnieść się do tej odpowiedzi , aby zobaczyć odpowiedni kod.

redmode
źródło
5
Jak sugeruje Henrik , dane naprawdę powinny być w „długim” formacie, ggplotobsługuje to bardziej naturalnie niż w „szerokim” formacie, którego używasz.
krlmlr
1
@Henrik: Nie, dziękuję za odpowiedź. Być może autor tej odpowiedzi może ją edytować, aby dobrze pasował do ggplotfilozofii ...
krlmlr 26.09.13
1
@krlmlr, próbowałem edytować swoją odpowiedź, aby bardziej jednoznacznie odpowiadała na pytanie. Sugerujemy dalsze aktualizacje. Twoje zdrowie.
Henrik
3
nauczył mnie definiowania x na ggplot (aes ()), a następnie y na geom _ * (). Miły!
Dan.
41

Myślę, że odpowiedź, której szukasz, to:

plot(first thing to plot)
plot(second thing to plot,add=TRUE)
użytkownik3749764
źródło
25
To nie wydaje się działać, daje "add" is not a graphical parameterostrzeżenie, a następnie drukuje drugi wykres na pierwszym.
Waldir Leoncio
8
@WaldirLeoncio patrz stackoverflow.com/questions/6789055/…
Alessandro Jacopson
Jedną z zalet tego rozwiązania jest to, że wydaje się utrzymywać spójność granic osi i tytułów. Niektóre z poprzednich metod powodują, że R rysuje dwa zestawy znaczników na osi y, chyba że przejdziesz przez trudność określenia większej liczby opcji. Nie trzeba dodawać, że posiadanie dwóch zestawów znaczników na osiach może być bardzo mylące.
RMurphy,
1
parametr add działa z niektórymi metodami wydruku, ale nie bazowy / domyślny w R
cloudcomputing
2
Mam ten sam błąd "add" is not a graphical parameter. Mój R jest R version 3.2.3 (2015-12-10). Możesz użyć par(new=TRUE)polecenia między tymi wykresami.
quepas
29

Użyj matplotfunkcji:

matplot(x, cbind(y1,y2),type="l",col=c("red","green"),lty=c(1,1))

użyj tego, jeśli y1i y2są oceniane w tych samych xpunktach. Skaluje oś Y, aby dopasować ją do tego, która wartość jest większa ( y1lub y2), w przeciwieństwie do niektórych innych odpowiedzi, które zostaną przycięte, y2jeśli będzie większa niż y1(rozwiązania ggplot w większości są w porządku).

Alternatywnie, a jeśli dwie linie nie mają tych samych współrzędnych x, ustaw granice osi na pierwszym wykresie i dodaj:

x1  <- seq(-2, 2, 0.05)
x2  <- seq(-3, 3, 0.05)
y1 <- pnorm(x1)
y2 <- pnorm(x2,1,1)

plot(x1,y1,ylim=range(c(y1,y2)),xlim=range(c(x1,x2)), type="l",col="red")
lines(x2,y2,col="green")

Dziwi mnie, że Q ma 4 lata i nikt nie wspomniał matplotani nie x/ylim...

Spacedman
źródło
25

tl; dr: Chcesz użyć curve(z add=TRUE) lub lines.


Nie zgadzam się z par(new=TRUE)tym, ponieważ spowoduje to podwójne wydrukowanie znaczników i etykiet osi. Na przykład

sinus i parabola

Dane wyjściowe plot(sin); par(new=T); plot( function(x) x**2 ).

Zobacz, jak pomieszane są etykiety osi pionowej! Ponieważ zakresy są różne, musisz ustawić ylim=c(lowest point between the two functions, highest point between the two functions), co jest mniej łatwe niż to, co zamierzam ci pokazać --- i znacznie mniej łatwe, jeśli chcesz dodać nie tylko dwie krzywe, ale wiele.


To, co zawsze myliło mnie w spiskowaniu, to różnica między curvei lines. (Jeśli nie pamiętasz, że są to nazwy dwóch ważnych poleceń drukowania, po prostu zaśpiewaj .)

Oto duża różnica między curvei lines.

curvewykreśli funkcję, np curve(sin). linesDziałki punktów z wartości x i y, takie jak: lines( x=0:10, y=sin(0:10) ).

A oto niewielka różnica: curvetrzeba się do niego zwrócić z add=TRUEtym, co próbujesz zrobić, przy lineszałożeniu, że dodajesz do istniejącej fabuły.

id i sinus

Oto wynik połączenia plot(0:2); curve(sin).


Za kulisami sprawdź methods(plot). I sprawdź body( plot.function )[[5]]. Kiedy wywołujesz plot(sin)R, odkrywa, że sinjest to funkcja (a nie wartości y) i używa plot.functionmetody, która kończy się wywołaniem curve. Podobnie curvenarzędzie przeznaczone do obsługi funkcji.

izomorfizmy
źródło
17

jeśli chcesz podzielić wykres na dwie kolumny (2 wykresy obok siebie), możesz to zrobić w następujący sposób:

par(mfrow=c(1,2))

plot(x)

plot(y) 

Link referencyjny

Hamed2005
źródło
16

Jak opisano w @redmode, możesz narysować dwie linie w tym samym urządzeniu graficznym, używając ggplot. W tej odpowiedzi dane były w „szerokim” formacie. Jednak podczas korzystania z ggplotniego najwygodniej jest przechowywać dane w ramce danych w „długim” formacie. Następnie, używając różnych „zmiennych grupujących” waes argumentach tematycznych, właściwości linii, takie jak rodzaj linii lub kolor, będą się różnić w zależności od zmiennej grupującej i pojawią się odpowiednie legendy.

W tym przypadku możemy zastosować colourestetykę, która dopasowuje kolor linii do różnych poziomów zmiennej w zbiorze danych (tutaj: y1 vs y2). Ale najpierw musimy stopić dane z szerokiego na długi format, używając np. Funkcji „stop” z reshape2pakietu. Inne metody przekształcania danych opisano tutaj: Przekształcanie data.frame z formatu szerokiego na długi .

library(ggplot2)
library(reshape2)

# original data in a 'wide' format
x  <- seq(-2, 2, 0.05)
y1 <- pnorm(x)
y2 <- pnorm(x, 1, 1)
df <- data.frame(x, y1, y2)

# melt the data to a long format
df2 <- melt(data = df, id.vars = "x")

# plot, using the aesthetics argument 'colour'
ggplot(data = df2, aes(x = x, y = value, colour = variable)) + geom_line()

wprowadź opis zdjęcia tutaj

Henrik
źródło
15

Jeśli używasz grafiki bazowej (tzn. Nie grafiki kratowej / siatki), możesz naśladować funkcję MATLAB, korzystając z funkcji punktów / linii / wielokątów, aby dodać dodatkowe szczegóły do ​​swoich wykresów bez rozpoczynania nowego wykresu. W przypadku układu wielopunktowego możesz użyć, par(mfg=...)aby wybrać, do którego działki chcesz dodać elementy.

Mccabral
źródło
14

Oznacza to, że możesz użyć punktów do wykreślenia.

plot(x1, y1,col='red')

points(x2,y2,col='blue')
burza mózgów
źródło
7

Zamiast przechowywać wartości do wykreślenia w tablicy, przechowuj je w macierzy. Domyślnie cała macierz będzie traktowana jako jeden zestaw danych. Jeśli jednak dodasz taką samą liczbę modyfikatorów do wykresu, np. Col (), ponieważ masz wiersze w macierzy, R zorientuje się, że każdy wiersz powinien być traktowany niezależnie. Na przykład:

x = matrix( c(21,50,80,41), nrow=2 )
y = matrix( c(1,2,1,2), nrow=2 )
plot(x, y, col("red","blue")

Powinno to działać, chyba że zestawy danych mają różne rozmiary.

żurawina
źródło
Daje to: Błąd w if (as.factor) {: argumentu nie można interpretować jako logicznego
baouss
5

Idiomatic Matlab plot(x1,y1,x2,y2)można przetłumaczyć na R, ggplot2na przykład w następujący sposób:

x1 <- seq(1,10,.2)
df1 <- data.frame(x=x1,y=log(x1),type="Log")
x2 <- seq(1,10)
df2 <- data.frame(x=x2,y=cumsum(1/x2),type="Harmonic")

df <- rbind(df1,df2)

library(ggplot2)
ggplot(df)+geom_line(aes(x,y,colour=type))

wprowadź opis zdjęcia tutaj

Zainspirowany przez podwójne wykresy Tingting Zhao z innym zakresem osi x za pomocą ggplot2 .

Alessandro Jacopson
źródło
5

Możesz użyć ggplotly()funkcji z pakietu plot , aby zamienić dowolny z przykładów gggplot2 tutaj na interaktywny, ale myślę, że ten rodzaj wykresu jest lepszy bez ggplot2 :

# call Plotly and enter username and key
library(plotly)
x  <- seq(-2, 2, 0.05)
y1 <- pnorm(x)
y2 <- pnorm(x, 1, 1)

plot_ly(x = x) %>%
  add_lines(y = y1, color = I("red"), name = "Red") %>%
  add_lines(y = y2, color = I("green"), name = "Green")

wprowadź opis zdjęcia tutaj

Mateo Sanchez
źródło
fabuła wygląda genialnie; czy to jest darmowe?
denis
@denis, istnieje nieograniczona liczba bezpłatnych publicznych kreślenia i płatnych prywatnych kreślenia lub opcji na miejscu. Zobacz stronę planów .
Mateo Sanchez
4
Dzielny pakiet R jest teraz w 100% darmowy i open source (licencja MIT). Możesz go używać z kontem działkowym lub bez niego.
Carson
4

Możesz również utworzyć fabułę za pomocą ggvis :

library(ggvis)

x  <- seq(-2, 2, 0.05)
y1 <- pnorm(x)
y2 <- pnorm(x,1,1)
df <- data.frame(x, y1, y2)

df %>%
  ggvis(~x, ~y1, stroke := 'red') %>%
  layer_paths() %>%
  layer_paths(data = df, x = ~x, y = ~y2, stroke := 'blue')

Spowoduje to utworzenie następującego wykresu:

wprowadź opis zdjęcia tutaj

epo3
źródło
2

Używanie plotly(dodawanie rozwiązania plotlyz pierwotną i wtórną osią y - wydaje się, że brakuje):

library(plotly)     
x  <- seq(-2, 2, 0.05)
y1 <- pnorm(x)
y2 <- pnorm(x, 1, 1)

df=cbind.data.frame(x,y1,y2)

  plot_ly(df) %>%
    add_trace(x=~x,y=~y1,name = 'Line 1',type = 'scatter',mode = 'lines+markers',connectgaps = TRUE) %>%
    add_trace(x=~x,y=~y2,name = 'Line 2',type = 'scatter',mode = 'lines+markers',connectgaps = TRUE,yaxis = "y2") %>%
    layout(title = 'Title',
       xaxis = list(title = "X-axis title"),
       yaxis2 = list(side = 'right', overlaying = "y", title = 'secondary y axis', showgrid = FALSE, zeroline = FALSE))

Zrzut ekranu z działającej wersji demo:

wprowadź opis zdjęcia tutaj

Saurabh Chauhan
źródło
Skompilowałem kod i nie działa, najpierw oznaczyłem błąd w%>% i usunąłem go, a następnie oznaczyłem błąd Error in library(plotly) : there is no package called ‘plotly’dlaczego?
Bellatrix
Czy zainstalowałeś pakiet plotly? Musisz zainstalować pakiet za pomocą install.packages("plotly")polecenia.
Saurabh Chauhan
1

możemy również użyć biblioteki kratowej

library(lattice)
x <- seq(-2,2,0.05)
y1 <- pnorm(x)
y2 <- pnorm(x,1,1)
xyplot(y1 + y2 ~ x, ylab = "y1 and y2", type = "l", auto.key = list(points = FALSE,lines = TRUE))

Dla określonych kolorów

xyplot(y1 + y2 ~ x,ylab = "y1 and y2", type = "l", auto.key = list(points = F,lines = T), par.settings = list(superpose.line = list(col = c("red","green"))))

wprowadź opis zdjęcia tutaj

Varn K.
źródło