Построение двух переменных в виде линий с использованием ggplot2 на одном графике


305

Очень новенький вопрос, но, скажем, у меня есть такие данные:

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)
  )

Как я могу построить как временные ряды, так var0и var1на одном графике с dateпомощью оси X, используя ggplot2? Бонусные баллы, если вы делаете var0и var1разных цветов, и могут включать в себя легенду!

Я уверен, что это очень просто, но я не могу найти никаких примеров там.

Ответы:


373

Для небольшого числа переменных вы можете построить график вручную:

ggplot(test_data, aes(date)) + 
  geom_line(aes(y = var0, colour = "var0")) + 
  geom_line(aes(y = var1, colour = "var1"))

3
хороший пример, но как настроить мои собственные цвета (например, черный и оранжевый) ?, потому что кажется, что вы используете в colour=качестве имени переменной.
Дарвин ПК

1
даже colour='var_names'как указано Хадли работает отлично. но @DaveX - будет более конкретным, если вы хотите выбрать определенные цвета, а не автоматически выбранные цвета с помощью функции.
I_m_LeMarque

Как я могу добавить легенду к нему?
user1700890

361

Общий подход заключается в преобразовании данных в длинный формат (используя melt()из пакета reshapeили reshape2) или gather()/ pivot_longer()из tidyrпакета:

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()

выход ggplot2

Также посмотрите этот вопрос о преобразовании данных из широкого в длинный.


8
Вы также можете использовать gather()функцию tidyrупаковки для расплавления данных:gather(test_data, variable, value, -date)
janosdivenyi

33

Вам нужно, чтобы данные были в «высоком» формате, а не в «широком» для ggplot2. «широкий» означает наличие наблюдения на строку с каждой переменной в виде отдельного столбца (как у вас сейчас). Вам необходимо преобразовать его в «высокий» формат, где у вас есть столбец, в котором указано имя переменной, и другой столбец, в котором указано значение переменной. Процесс перехода от широкого к высокому обычно называют «таянием». Вы можете использовать, tidyr::gatherчтобы растопить ваш фрейм данных:

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()

несколько серий ggplot2

Просто чтобы прояснить, dataчто ggplotпотребляет после прохождения через него gatherвыглядит так:

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

13

Используя ваши данные:

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))

Я создаю стековую версию, с которой ggplot()хотелось бы работать:

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

В этом случае создание stackedбыло довольно легким, поскольку нам нужно было всего лишь выполнить пару манипуляций, но reshape()и reshapeи reshape2может быть полезно, если у вас есть более сложный набор реальных данных для манипуляции.

Как только данные находятся в этой суммированной форме, требуется всего лишь простой ggplot()вызов для создания нужного вам графика со всеми дополнительными функциями (одна из причин, почему высокоуровневые пакеты построения графиков нравятся latticeи ggplot2так полезны):

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

Я оставлю это вам, чтобы привести в порядок метки осей, заголовок легенды и т. Д.

НТН


1
Я думаю, что у вас есть неуместные паренсы в вашем коде там. Я думаю, что это то, что вы после: сложены <- с (test_data, data.frame (значение = c (var0, var1), переменная = фактор (rep (c ("Var0", "Var1"))), каждый = NROW (test_data), Dates = rep (date, 2))). Кроме того, какова цель столбца «каждый»? И разве это не просто более запутанный и менее эффективный способ расплавления данных, как показывает rcs? Я полагаю, я мог бы представить себе случай, когда расплав не справился бы с работой, но это почти наверняка правильный инструмент для этой работы, если я что-то упустил?
Погоня

1
@ chase, извините, это Emacs ESS неправильно делает отступ. каждый является аргументом rep(), так что мы действительно получаем только 3 столбца stacked. Я отредактирую код, чтобы сделать отступ более понятным.
Гэвин Симпсон

1
@гнаться; Ваш комментарий о melt()хорошо принят, и я отмечаю, что пакет reshape [2] будет полезен здесь. Я не настолько знаком с reshape2, и для такой простой манипуляции сделать это вручную сложнее, чем призывать melt(), это было меньше усилий, так как мне не нужно было читать, как использовать melt(). И rcs подкрался с его ответом, пока я производил мой; когда я начал отвечать, ответов не было. более чем один способ снять шкуру с кошки - как говорится! ;-)
Гэвин Симпсон

7

Я также новичок в R, но, пытаясь понять, как работает ggplot, я думаю, у меня есть другой способ сделать это. Я просто поделюсь, вероятно, не как совершенное идеальное решение, а добавлю несколько разных точек зрения.

Я знаю, что ggplot лучше работает с фреймами данных, но, возможно, иногда полезно знать, что вы можете напрямую построить два вектора без использования фрейма данных.

Загрузка данных. Длина вектора исходной даты равна 100, тогда как var0 и var1 имеют длину 50, поэтому я только отображаю доступные данные (первые 50 дат).

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)    

Черчение

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

введите описание изображения здесь

Однако я не смог добавить правильную легенду, используя этот формат. Кто-нибудь знает как?


1
Это добавляет легенду 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
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.