【问题标题】:date format when plotting a time series in R在 R 中绘制时间序列时的日期格式
【发布时间】:2017-11-01 03:57:06
【问题描述】:

我的数据框df 是一个包含DatumOpbrengst 变量的每日时间序列。 Datum 变量介于 2016010120170521 之间。

      Datum  Opbrengst
1   20160101  40609276
2   20160102  79381098
3   20160103 114653269
4   20160104 126044535
5   20160105 180472785
...

我想做预测,所以我要做的第一件事是绘制系列以查看系列是否静止(如果它具有季节性)。

但是,日期变量是numeric,所以当我绘制系列时,

 ggplot(data=df, aes(x=Datum , y=Opbrengst, group=1)) +
    geom_line()+
    geom_point()

变成这样:

问题在于该系列跨越了多年,这就是为什么 R 将其视为 numeric series,而不是 time series

我尝试使用this website中的方法将其转换为日期

 df$Datum = as.Date(df$Datum)

但结果不正确:

 "57166-06-26" "57166-06-27" "57166-06-28" "57166-06-29" "57166-06-30" "57166-07-01"

我的问题是:

  1. 如何将基准变量更改为日期格式,以便在绘制图形时不会出现问题?因为稍后我确实需要同时进行dailyweekly 预测。

  2. 我知道如果我使用plot.ts(),那么我不需要更改时间格式。我也可以在ggplot 中做时间序列图吗?

[编辑]

这是数据的一个样本:

df <- structure(list(Datum = 20160101:20160120, Opbrengst = c(40609276, 
79381098, 114653269, 126044535, 180472785, 169286880, 149272135, 
133645566, 70171285, 150029065, 149172032, 107843808, 138196732, 
136460905, 133595660, 61716435, 137309503, 193201850, 140766980, 
129859068)), .Names = c("Datum", "Opbrengst"), row.names = c(NA, 
20L), class = "data.frame")

【问题讨论】:

  • 你能用 dput() 提供一个可重现的例子吗?
  • 试试as.Date.character(df$Datum, format = "%Y %M %d")
  • @SBista as.Date.character(df$Datum, format = "%Y %M %d") 返回错误日期,请参阅here
  • @UweBlock 对不起,我的错。我的意思是as.Date.character(Datum, "%Y %m %d")。请注意,它是%m 而不是%M。我想%M 的日期没有%m 指的是month (00-12)

标签: r date ggplot2 time-series prediction


【解决方案1】:

这里的问题是将df$Datum 转换为Date 类。与ggplot2无关

将样本数据创建为integer,包括新年:

(Datum <- c(20151224:20151231, 20160101:20160107))
 [1] 20151224 20151225 20151226 20151227 20151228 20151229 20151230 20151231 20160101
[10] 20160102 20160103 20160104 20160105 20160106 20160107

anytime::anydate()lubridate::ymd() 似乎可以直接将整数 Datum 转换为 character,而无需强制转换。

anytime::anydate(Datum)
# [1] "2015-12-24" "2015-12-25" "2015-12-26" "2015-12-27" "2015-12-28" "2015-12-29"
# [7] "2015-12-30" "2015-12-31" "2016-01-01" "2016-01-02" "2016-01-03" "2016-01-04"
#[13] "2016-01-05" "2016-01-06" "2016-01-07"

lubridate::ymd(Datum)
# [1] "2015-12-24" "2015-12-25" "2015-12-26" "2015-12-27" "2015-12-28" "2015-12-29"
# [7] "2015-12-30" "2015-12-31" "2016-01-01" "2016-01-02" "2016-01-03" "2016-01-04"
#[13] "2016-01-05" "2016-01-06" "2016-01-07"

as.Date() 在这里抛出错误:

as.Date(Datum)
#Error in as.Date.numeric(Datum) : 'origin' must be supplied

as.Date(Datum, "%Y%m%d")
#Error in charToDate(x) : 
#  character string is not in a standard unambiguous format

Datum 需要先强制转换为character

as.Date(as.character(Datum), "%Y%m%d")
# [1] "2015-12-24" "2015-12-25" "2015-12-26" "2015-12-27" "2015-12-28" "2015-12-29"
# [7] "2015-12-30" "2015-12-31" "2016-01-01" "2016-01-02" "2016-01-03" "2016-01-04"
#[13] "2016-01-05" "2016-01-06" "2016-01-07"

请注意,格式字符串是"%Y%m%d" 与小写m 不是 "%Y%M%d" 与大写M。有趣的是,"%Y %m %d" 穿插空白似乎也可以在这里工作。


完整示例

# create data
df <- data.frame(
  Datum = c(20151220:20151231, 20160101:20160108),
  Opbrengst = c(40609276, 79381098, 114653269, 126044535, 180472785, 169286880, 
                149272135, 133645566, 70171285, 150029065, 149172032, 107843808, 
                138196732, 136460905, 133595660, 61716435, 137309503, 193201850, 
                140766980, 129859068))

# coerce to class Date
df$Datum <- anytime::anydate(df$Datum)

library(ggplot2)
ggplot(df, aes(Datum, Opbrengst)) + geom_line() + geom_point()

请注意,新年的间隔已经过去。

【讨论】:

  • @Sheryl 我使用了双冒号运算符:: 来告诉 R 必须使用哪个包中的特定函数。则无需加载library(anytime)。这避免了一堆加载的包使命名空间混乱,并避免了可能导致的名称冲突。在编程中,它提高了可维护性。
【解决方案2】:

[编辑]

%M 更改为%m

有很多方法可以做到这一点。三个简单的:

df <- structure(list(Datum = 20160101:20160120, Opbrengst = c(40609276, 79381098, 114653269, 126044535, 180472785, 169286880, 149272135, 133645566, 70171285, 150029065, 149172032, 107843808, 138196732, 136460905, 133595660, 61716435, 137309503, 193201850, 140766980, 129859068)), .Names = c("Datum", "Opbrengst"), row.names = c(NA, 20L), class = "data.frame")

# 1. Using the as.Date function (as sugges5ted by @SBista) to create a date object: 
df$Datum <- as.Date.character(df$Datum, format = "%Y %m %d")

# 2. Or create a POSIXct object:
# df$Datum <- strptime(df$Datum, format = "%Y %m %d")  

# 3. Using 'lubridate' to create a Date or POSIXct object (see 'tz' argument in ?ymd):
# df$Datum <- lubridate::ymd(df$Datum, tz = NULL)

ggplot(data=df, aes(x=Datum , y=Opbrengst)) +
  geom_line()+
  geom_point()

结果:

您的示例的问题在于您没有提供“格式”参数,因此 R 不知道它是年月日。

【讨论】:

  • 谢谢,@raistlin!我选择了您提出的 #1 和 #3 方法,但我的图表看起来仍然一样。我检查了df,确实 Datum 已经变成了日期格式。
  • 您能否将dput(df) 的结果粘贴到您的原始答案中以了解数据的样子?
  • 输出被截断——我假设你有很多观察结果。您可以只输入前 20 行:dput(df[1:20,]) 另外,最好输入原始的 df
  • 我用dput(df[1:20,])重新编辑并更新了结果。
  • 不,问题是错误的格式字符串"%Y %M %d" 应为"%Y %m %d"(小写m)。 %M 是几分钟,%m 是几个月。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-05-08
  • 1970-01-01
  • 1970-01-01
  • 2017-11-29
  • 2017-04-24
  • 2011-12-09
相关资源
最近更新 更多