【问题标题】:Dates with month and day in time series plot in ggplot2 with facet for yearsggplot2 中的时间序列中带有月份和日期的日期,带有多年的刻面
【发布时间】:2015-07-10 13:22:16
【问题描述】:

当在 ggplot2 中使用 facet 多年时,我希望在时间序列图的 x 轴上同时拥有 monthday。我的 MWE 如下:

set.seed(12345)
Date <- seq(as.Date("2010/1/1"), as.Date("2014/1/1"), "week")
Y <- rnorm(n=length(Date), mean=100, sd=1)
df <- data.frame(Date, Y)

df$Year <- format(df$Date, "%Y")
df$Month <- format(df$Date, "%b")
df$Day <- format(df$Date, "%d")

df$MonthDay <- format(df$Date, "%d-%b")


p <- ggplot(data=df, mapping=aes(x=MonthDay, y=Y, shape=Year, color=Year)) + geom_point() +geom_line(aes(group = 1))
p <- p + facet_grid(facets = Year ~ ., margins = FALSE) + theme_bw()
print(p)

我尝试使用以下命令控制 x 轴标签

p + scale_y_continuous() + scale_x_date(labels = date_format("%d-%b"))

但它会引发以下错误消息。

Error: Invalid input: date_trans works with objects of class Date only

【问题讨论】:

  • 感谢@G.Grothendieck 的评论和对我的问题的兴趣。使用x=Date 将不必要地在 x 轴上花费所有四年,这不是必需的。

标签: r ggplot2 time-series


【解决方案1】:

你很亲密。您希望 x 轴衡量您所在年份的位置,但您将其作为字符向量,因此要标记每个点。如果你改为用一个连续变量来表示这一点,你可能会得到更好的结果。一年中的某一天是一个连续变量。

df$DayOfYear <- as.numeric(format(df$Date, "%j"))
ggplot(data = df,
       mapping = aes(x = DayOfYear, y = Y, shape = Year, colour = Year)) +
  geom_point() +
  geom_line() +
  facet_grid(facets = Year ~ .) +
  theme_bw()

可以使用适当的标签函数将轴格式化为更类似于日期的格式,但仍然无法以非常日期感知的方式找到中断。 (除此之外,还有一个NA 问题。)

ggplot(data = df,
       mapping = aes(x = DayOfYear, y = Y, shape = Year, colour = Year)) +
  geom_point() +
  geom_line() +
  facet_grid(facets = Year ~ .) +
  scale_x_continuous(labels = function(x) format(as.Date(as.character(x), "%j"), "%d-%b")) +
  theme_bw()

为了获得漂亮的约会休息时间,可以使用不同的变量。与原始数据具有相同年份的日期,但只有一年。在这种情况下,2000 年是闰年。与此相关的问题主要与闰日有关,但如果您不关心这一点(非闰年的 3 月 1 日将与闰年的 2 月 29 日一致,等等),您可以使用:

df$CommonDate <- as.Date(paste0("2000-",format(df$Date, "%j")), "%Y-%j")
ggplot(data = df,
       mapping = aes(x = CommonDate, y = Y, shape = Year, colour = Year)) +
  geom_point() +
  geom_line() +
  facet_grid(facets = Year ~ .) +
  scale_x_date(labels = function(x) format(x, "%d-%b")) +
  theme_bw()

【讨论】:

  • 优秀的答案。 @Brian,拥有几年的每日数据并希望将年份相互叠加在我看来似乎是一项非常常见的任务。您是否知道任何采用日期变量、使用“CommonDate”方法而没有闰日问题的包?
  • @Dan 对不起,我不知道有这样的包。有几个部分日期/部分时间在诸如此类的上下文中会很有用,但我不知道它们被收集的任何地方。
【解决方案2】:

坚持使用您的代码@MYaseen208 来创建数据。

当你绘制它时使用x = Date 并使用下面的

p <- ggplot(data = df, aes(x = Date, y = Y, shape = Year, color = Year)) +
  geom_point() + geom_line(aes(group = 1))
  #adding facet and using facet_wrap with free x scales
  p <- p + facet_wrap(~Year,ncol=1, scales = "free_x") + theme_bw()+
scale_y_continuous() + 
scale_x_date(labels = date_format("%d-%b"), breaks = date_breaks("2 weeks")) +
 theme(axis.text.x = element_text(angle = 90, vjust = 0.5, size = 8))

我使用 facet_wrap 来获得免费的 x_axis 刻度。当您划分数据时,我们无法获得每年相同的日月组合。

【讨论】:

    【解决方案3】:

    这似乎可以做到...我只是手动创建了标签...

    library("ggplot2")
    library("scales")
    set.seed(12345)
    Date <- seq(as.Date("2010/1/1"), as.Date("2014/1/1"), "week")
    Y <- rnorm(n=length(Date), mean=100, sd=1)
    df <- data.frame(Date, Y)
    
    df$Year <- format(df$Date, "%Y")
    df$Month <- format(df$Date, "%b")
    df$Day <- format(df$Date, "%d")
    
    df$MonthDay <- format(df$Date, "%d-%b")
    df$MonthDay2 <- df$MonthDay
    # only show every third label... otherwise it's too crowded
    df$MonthDay2[as.numeric(row.names(df))%%3!=0] <- ""
    labels <- df$MonthDay2
    
    p <- ggplot(data=df, mapping=aes(x=MonthDay, y=Y, shape=Year, color=Year)) + geom_point() +geom_line(aes(group = 1))
    p <- p + facet_grid(facets = Year ~ ., margins = FALSE) + theme_bw()
    p + scale_y_continuous() + scale_x_discrete(labels=labels) + 
      theme(axis.text.x = element_text(angle = 90, vjust = 0.5, size = 8))
    

    【讨论】:

    • 优秀的选择@infominer。
    • 是的,很好,我没有注意到格式没有做任何事情。我在上面对其进行了编辑,然后手动构建了标签。
    【解决方案4】:

    对@Brian Diggs 的保留原始日期和月份(3 月 1 日保留为 3 月 1 日而不是 2 月 29 日)方法的修改是将日期强制转换为字符串,然后替换年份:

    library(lubridate)
    library(stringr)
    df$CommonDate <- ymd(paste0("2000-",str_sub(as.character(df$Date),-5)))
    

    然后您可以继续:

    ggplot(data = df,
       mapping = aes(x = CommonDate, y = Y, shape = Year, colour = Year)) +
      geom_point() +
      geom_line() +
      facet_grid(facets = Year ~ .) +
      scale_x_date(labels = function(x) format(x, "%d-%b")) +
      theme_bw()
    

    【讨论】:

    • 或者,您可以直接将年份替换为 lubridate year(df$CommonDate)&lt;-2000 然后继续。
    • 是否可以使用 CommonDate 但从 11 月到 2 月进行绘图? (捕捉不同年份的冬季)
    • 这可能是一个新问题。您应该能够创建一个跨年的绘图变量,因此将 11 月/12 月日期分配给 1999 年,将 1 月/2 月日期分配给 2000 年。我还将为季节创建一个变量,将 2019 年 11 月与 2020 年 1 月放在一起,而不是 2019 年 1 月。然后,当您绘制时,它应该跨越多年,并且您的方面基于新的季节变量。水文学家经常用“水年”做类似的事情,在我所在的地区,从 10 月 1 日到 9 月 30 日。
    猜你喜欢
    • 2021-09-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-12-04
    • 1970-01-01
    • 2015-06-01
    • 1970-01-01
    • 2018-10-15
    相关资源
    最近更新 更多