Wykreślanie dwóch zmiennych jako linii za pomocą ggplot2 na tym samym wykresie

305

Bardzo nowe pytanie, ale powiedz, że mam takie dane:

test_data <-
  data.frame(
    var0 = 100 + c(0, cumsum(runif(49, -20, 20))),
    var1 = 150 + c(0, cumsum(runif(49, -10, 10))),
    date = seq(as.Date("2002-01-01"), by="1 month", length.out=100)
  )

Jak mogę wykreślić zarówno szeregi czasowe, jak var0i var1ten sam wykres za pomocądate na osi X, używając ggplot2? Punkty bonusowe, jeśli wykonasz var0i var1różne kolory, i mogą zawierać legendę!

Jestem pewien, że jest to bardzo proste, ale nie mogę znaleźć żadnych przykładów.

fmark
źródło

Odpowiedzi:

373

W przypadku niewielkiej liczby zmiennych możesz samodzielnie utworzyć wykres:

ggplot(test_data, aes(date)) + 
  geom_line(aes(y = var0, colour = "var0")) + 
  geom_line(aes(y = var1, colour = "var1"))
Hadley
źródło
3
fajny przykład, ale jak dostosować własne kolory (np. czarny i pomarańczowy) ?, ponieważ wydaje się, że używasz colour=jako nazwy zmiennej.
Darwin PC
1
nawet colour='var_names'jak określono przez hadley działa dobrze. ale @DaveX - byłoby bardziej szczegółowe, jeśli ktoś chce wybrać określone kolory zamiast automatycznie wybieranych kolorów przez funkcję.
I_m_LeMarque
Jak mogę dodać legendę?
user1700890
361

Ogólne podejście polega na konwertowaniu danych na długi format (przy użyciu melt()z pakietu reshapelub reshape2) lub gather()/ pivot_longer()z tidyrpakietu:

library("reshape2")
library("ggplot2")

test_data_long <- melt(test_data, id="date")  # convert to long format

ggplot(data=test_data_long,
       aes(x=date, y=value, colour=variable)) +
       geom_line()

wyjście ggplot2

Zobacz także to pytanie dotyczące przekształcania danych z szerokiego na długi.

rcs
źródło
8
Możesz także użyć gather()funkcji tidyrpakiet do stopienia danych:gather(test_data, variable, value, -date)
janosdivenyi
33

Musisz mieć dane w formacie „wysokim” zamiast „szerokiego” dla ggplot2. „szeroki” oznacza obserwację w wierszu z każdą zmienną jako inną kolumną (tak jak teraz). Musisz przekonwertować go na format „wysoki”, w którym masz kolumnę z nazwą zmiennej i inną kolumnę z informacją o wartości zmiennej. Proces przechodzenia z szerokiego na wysoki jest zwykle nazywany „topieniem”. Możesz użyć tidyr::gatherdo stopienia ramki danych:

library(ggplot2)
library(tidyr)

test_data <-
  data.frame(
    var0 = 100 + c(0, cumsum(runif(49, -20, 20))),
    var1 = 150 + c(0, cumsum(runif(49, -10, 10))),
    date = seq(as.Date("2002-01-01"), by="1 month", length.out=100)
  )
test_data %>%
    gather(key,value, var0, var1) %>%
    ggplot(aes(x=date, y=value, colour=key)) +
    geom_line()

wiele serii ggplot2

Żeby było jasne, dataże ggplotto, co zużywa po przepuszczeniu, gatherwygląda następująco:

date        key     value
2002-01-01  var0    100.00000
2002-02-01  var0    115.16388 
...
2007-11-01  var1    114.86302
2007-12-01  var1    119.30996
RubenLaguna
źródło
13

Korzystanie z danych:

test_data <- data.frame(
var0 = 100 + c(0, cumsum(runif(49, -20, 20))),
var1 = 150 + c(0, cumsum(runif(49, -10, 10))),
Dates = seq.Date(as.Date("2002-01-01"), by="1 month", length.out=100))

Tworzę wersję skumulowaną, z którą ggplot()chciałbym pracować:

stacked <- with(test_data,
                data.frame(value = c(var0, var1),
                           variable = factor(rep(c("Var0","Var1"),
                                                 each = NROW(test_data))),
                           Dates = rep(Dates, 2)))

W tym przypadku wytwarzania stackedbyło dość proste, jak mieliśmy tylko zrobić parę manipulacji, ale reshape()i reshape, a reshape2może być przydatne, jeśli mają bardziej złożony zestaw danych rzeczywistych do manipulowania.

Gdy dane są już w tej skumulowanej formie, wystarczy tylko jedno ggplot()wywołanie, aby utworzyć żądany wykres ze wszystkimi dodatkami (jeden z powodów, dla których pakiety wydruku wyższego poziomu lubią latticei ggplot2są tak przydatne):

require(ggplot2)
p <- ggplot(stacked, aes(Dates, value, colour = variable))
p + geom_line()

Pozostawiam do uporządkowania etykiet osi, tytułu legendy itp.

HTH

Gavin Simpson
źródło
1
Wydaje mi się, że masz tam źle umieszczone pareny. Myślę, że po to jesteś: ułożone <- z (test_data, data.frame (wartość = c (var0, var1), zmienna = współczynnik (rep (c („Var0”, „Var1”))), each = NROW (dane testowe), Daty = rep (data, 2))). Jaki jest cel kolumny „każdy”? Czy to nie tylko bardziej skomplikowany i mniej wydajny sposób stopienia danych, jak pokazano w rcs? Wydaje mi się, że mógłbym sobie wyobrazić przypadek, w którym stopienie nie wykonałoby pracy, ale prawie na pewno jest to odpowiednie narzędzie do tej pracy, chyba że czegoś brakuje?
Chase
1
@ Chase, przepraszam, to znaczy, że Emacs ESS źle się wcina. każdy jest argumentem rep(), więc naprawdę otrzymujemy tylko 3 cols stacked. Zmodyfikuję kod, aby wyraźniejsze było wcięcie.
Gavin Simpson,
1
@pościg; twój komentarz na temat melt()jest dobrze przyjęty i zauważam, że przydatny byłby tutaj pakiet reshape [2]. Nie jestem zbyt obeznany z reshape2 i dla tak prostej manipulacji ręczne wykonanie tego zadania jest bardziej skomplikowane niż wezwanie do melt(), że było to mniej wysiłku, ponieważ nie musiałem czytać, jak go używać melt(). I rcs wkradł się z jego odpowiedzią, kiedy ja produkowałem moją; kiedy zacząłem odpowiadać, nie było odpowiedzi. więcej niż jeden sposób na skórowanie kota - jak mówią! ;-)
Gavin Simpson
7

Jestem również nowy w R, ale próbując zrozumieć, jak działa ggplot, myślę, że mam inny sposób, aby to zrobić. Po prostu udostępniam prawdopodobnie nie jako kompletne idealne rozwiązanie, ale dodając kilka różnych punktów widzenia.

Wiem, że ggplot jest lepiej przystosowany do pracy z ramkami danych, ale może czasem warto też wiedzieć, że możesz bezpośrednio wykreślić dwa wektory bez użycia ramki danych.

Ładowanie danych. Oryginalna długość wektora daty wynosi 100, podczas gdy var0 i var1 mają długość 50, więc wykreślam tylko dostępne dane (pierwsze 50 dat).

var0 <- 100 + c(0, cumsum(runif(49, -20, 20)))
var1 <- 150 + c(0, cumsum(runif(49, -10, 10)))
date <- seq(as.Date("2002-01-01"), by="1 month", length.out=50)    

Konspiratorstwo

ggplot() + geom_line(aes(x=date,y=var0),color='red') + 
           geom_line(aes(x=date,y=var1),color='blue') + 
           ylab('Values')+xlab('date')

wprowadź opis zdjęcia tutaj

Nie byłem jednak w stanie dodać poprawnej legendy przy użyciu tego formatu. Czy ktoś wie jak?

Papalagui
źródło
1
To dodaje legendę ggplot() + geom_line(aes(x=date,y=var0, group=1, colour = 'red')) + geom_line(aes(x=date,y=var1, group = 2, colour = 'blue')) + ylab('Values')+xlab('date')
Flurbius