在同一个图上使用ggplot2将两个变量画成直线

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

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在同一图形上绘制时间序列var0var1,并在x轴上使用date ?如果你让var0var1有不同的颜色,还可以加上一个图例!

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

596883 次浏览

使用你的数据:

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()reshapereshape2可能会有用。

一旦数据以这种堆叠形式存在,它只需要一个简单的ggplot()调用就可以生成你想要的包含所有额外内容的图形(这也是为什么像latticeggplot2这样的高级绘图包如此有用的原因之一):

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

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

HTH

一般的方法是将数据转换为长格式(使用包reshapereshape2中的melt())或从包tidyr中的gather()/pivot_longer():

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

< img src = " https://i.imgur.com/1449YUl.png " alt = " / >

另请参阅这个问题关于从宽到长重塑数据的内容。

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

ggplot(test_data, aes(date)) +
geom_line(aes(y = var0, colour = "var0")) +
geom_line(aes(y = var1, colour = "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()

multiple series ggplot2

澄清一下,ggplot在通过gather进行管道处理后所消耗的data是这样的:

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

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

enter image description here

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