这是一个非常新颖的问题,但假设我有这样的数据:

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

如何使用ggplot2在同一图形上绘制时间序列var0和var1,日期在x轴上?如果你让var0和var1有不同的颜色,还可以加上图例!

我相信这很简单,但我找不到任何例子。


当前回答

对于ggplot2,数据需要采用“tall”格式,而不是“wide”格式。“wide”表示每行都有一个观察,每个变量作为不同的列(就像您现在所做的那样)。您需要将其转换为“tall”格式,其中有一列告诉您变量的名称,另一列告诉您变量的值。从宽到高的过程通常被称为“融化”。你可以使用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()

为了弄清楚,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

其他回答

对于少量变量,你可以自己手动构建图:

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

使用你的数据:

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非常容易,因为我们只需要做几个操作,但是如果您需要操作一个更复杂的真实数据集,那么重塑()、重塑和重塑2可能会很有用。

一旦数据以这种堆叠形式出现,它只需要一个简单的ggplot()调用就可以生成你想要的带有所有额外功能的图(这也是为什么像lattice和ggplot2这样的高级绘图包如此有用的原因之一):

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

我将把它留给你整理轴标签,图例标题等。

HTH

一般的方法是将数据转换为长格式(使用来自包重塑或重塑2的melt())或来自包tidyr的gather()/pivot_long ():

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

## convert to long format with tidyr::pivot_longer
test_data_long_tidyr <- pivot_longer(test_data, cols = starts_with("var"))

ggplot(data=test_data_long_tidyr,
       aes(x=date, y=value, colour=name)) +
  geom_line() ## output not shown, it's equivalent to the below graph (with a tiny difference in the legend title)

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

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

另请参阅关于从宽到长重新塑造数据的问题。

我对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')

然而,我不能添加一个正确的图例使用这种格式。有人知道怎么做吗?

对于ggplot2,数据需要采用“tall”格式,而不是“wide”格式。“wide”表示每行都有一个观察,每个变量作为不同的列(就像您现在所做的那样)。您需要将其转换为“tall”格式,其中有一列告诉您变量的名称,另一列告诉您变量的值。从宽到高的过程通常被称为“融化”。你可以使用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()

为了弄清楚,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