使用ggplot()在同一图上绘制多个时间序列

50

我对R还比较陌生,正在尝试使用ggplot2同时绘制两个时间序列线(当然要使用不同的颜色)。我有两个数据框,第一个数据框有“X的百分比变化”和“日期”列,第二个数据框也有“Y的百分比变化”和“日期”列,即两个数据框都有一个相同值的“日期”列,而“百分比变化”列的数值不同。我想使用ggplot2在一个图中绘制这两个数据框的“百分比变化”列与“日期”(共同)的关系。我在网上找到的例子都是使用同一个数据框中的不同变量来实现这一点,但我找不到任何使用两个数据框来绘制图形的方法。我不想将两个数据框合并,而是想保持它们分开。以下是我正在使用的代码:

ggplot(jobsAFAM, aes(x=jobsAFAM$data_date, y=jobsAFAM$Percent.Change)) + geom_line() +
  xlab("") + ylab("")

但是这段代码只会生成一行,我希望在其上面再添加一行。 非常感谢任何帮助。TIA。

6个回答

111

ggplot 允许你有多个图层,这就是你应该利用的。

在下面创建的图中,你可以看到有两个 geom_line 语句分别针对你的数据集并将它们一起绘制在一个图上。如果你想要添加其他数据集、绘图或者图表的特性,比如轴标签,你可以扩展这个逻辑。

library(ggplot2)

jobsAFAM1 <- data.frame(
  data_date = runif(5,1,100),
  Percent.Change = runif(5,1,100)
)

jobsAFAM2 <- data.frame(
  data_date = runif(5,1,100),
  Percent.Change = runif(5,1,100)
)

ggplot() + 
  geom_line(data = jobsAFAM1, aes(x = data_date, y = Percent.Change), color = "red") +
  geom_line(data = jobsAFAM2, aes(x = data_date, y = Percent.Change), color = "blue") +
  xlab('data_date') +
  ylab('percent.change')

2
谢谢 @TheComeOnMan!! 这个运作得非常好;我能合并图例吗? - SamV
1
我该如何添加图例,@TheComeOnMan? - Álvaro A. Gutiérrez-Vargas

49
如果两个数据框具有相同的列名,则您应将一个数据框添加到 ggplot() 调用内,并在 ggplot() 调用的 aes() 中命名 x 和 y 值。然后添加第一个 geom_line() 用于第一条线,并使用 data=df2(其中 df2 是您的第二个数据帧)添加第二个 geom_line() 调用。如果需要在不同颜色的线条中则在每个 geom_line()aes() 中添加color=和每条线的名称。
df1<-data.frame(x=1:10,y=rnorm(10))
df2<-data.frame(x=1:10,y=rnorm(10))

ggplot(df1,aes(x,y))+geom_line(aes(color="First line"))+
  geom_line(data=df2,aes(color="Second line"))+
  labs(color="Legend text")

在此输入图片描述


1
非常感谢您的回答,它完全达到了我所期望的。 - Patthebug
@Didzis 不错的例子,但如果我想应用自定义颜色(例如黑色和橙色)和名称怎么办?看起来你正在使用color=作为“y”名称。 - Darwin PC
3
如果您需要更改图例内部的颜色和标签,则可以使用scale_color_manual() - Didzis Elferts
@DidzisElferts 如果df2中的x和y值不同怎么办? - WaterRocket8236

5

我知道这已经有些过时了,但它仍然具有相关性。您可以利用reshape2::melt函数将数据框转换为适合ggplot2的更友好的结构。

优点:

  • 允许您绘制任意数量的折线
  • 每条折线使用不同的颜色
  • 为每条折线添加图例
  • 仅需一次调用ggplot/geom_line即可实现

缺点:

  • 需要一个额外的包(reshape2)
  • 初始时melt函数使用不太直观

例如:

jobsAFAM1 <- data.frame(
  data_date = seq.Date(from = as.Date('2017-01-01'),by = 'day', length.out = 100),
  Percent.Change = runif(5,1,100)
)

jobsAFAM2 <- data.frame(
  data_date = seq.Date(from = as.Date('2017-01-01'),by = 'day', length.out = 100),
  Percent.Change = runif(5,1,100)
)

jobsAFAM <- merge(jobsAFAM1, jobsAFAM2, by="data_date")

jobsAFAMMelted <- reshape2::melt(jobsAFAM, id.var='data_date')

ggplot(jobsAFAMMelted, aes(x=data_date, y=value, col=variable)) + geom_line()

enter image description here


reshape2已经过时了,最好直接使用它的继承者dplyr。 - Fitzroy Hogsflesh
嗨@FranzPlumpton。您能否举个使用dplyr的例子? - Chris Njuguna

5

我更喜欢使用ggfortify库。它是ggplot2的封装器,可以识别autoplot函数内部对象的类型,并选择最佳的ggplot方法进行绘图。至少我不必记住ggplot2的语法。

library(ggfortify)
ts1 <- 1:100
ts2 <- 1:100*0.8
autoplot(ts( cbind(ts1, ts2)  , start = c(2010,5), frequency = 12 ),
         facets = FALSE)

Plot


3

这是旧的内容,请更新新的整洁工作流程,不要忘记上述内容。

library(tidyverse)

jobsAFAM1 <- tibble(
    date = seq.Date(from = as.Date('2017-01-01'),by = 'day', length.out = 5),
    Percent.Change = runif(5, 0,1)
    ) %>% 
    mutate(serial='jobsAFAM1')
jobsAFAM2 <- tibble(
    date = seq.Date(from = as.Date('2017-01-01'),by = 'day', length.out = 5),
    Percent.Change = runif(5, 0,1)
    ) %>% 
    mutate(serial='jobsAFAM2')
jobsAFAM <- bind_rows(jobsAFAM1, jobsAFAM2)

ggplot(jobsAFAM, aes(x=date, y=Percent.Change, col=serial)) + geom_line()

@Chris Njuguna

tidyr::gather()是在 tidyverse 工作流程中将宽格式数据框转换为长格式整洁布局的函数,然后 ggplot 可以绘制多个系列。

gather


@visitanz,采用更新的方法似乎是保持这个问题开放的好理由。您能否创建一个类似于之前答案/评论中的玩具示例? - Chris Njuguna
@Chris Njuguna,我已经在tidyverse工作流程中更改了你的示例代码。 - visitantz
@visitanz 很棒! - Chris Njuguna

1

另一种方法是将数据框绑定在一起,并将它们分配为它们所表示的变量类型。这将使您可以以更加整洁的方式使用完整数据集。

library(ggplot2)
library(dplyr)

df1 <- data.frame(dates = 1:10,Variable = rnorm(mean = 0.5,10))
df2 <- data.frame(dates = 1:10,Variable = rnorm(mean = -0.5,10))

df3 <- df1 %>%
  mutate(Type = 'a') %>%
  bind_rows(df2 %>%
              mutate(Type = 'b'))


ggplot(df3,aes(y = Variable,x = dates,color = Type)) + 
  geom_line()

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接