【问题标题】:Plot monthly figures out of 10min data从 10 分钟的数据中绘制月度数据
【发布时间】:2017-03-09 01:43:53
【问题描述】:

我想从 10 分钟时间序列中生成每月图。每个数据集的时间序列的开始和结束都不同,因此它应该可以正常工作。此外,还应为不同的变量生成图。

多年来,我有一个非常丑陋的解决方案,其中有一个循环,几个月后又有一个循环,虽然有效,但也会产生一些空的额外情节。我希望代码使它更易于理解。

library(dplyr)
library(readr)
library(tidyverse)
library(ggplot2)
library(lubridate)

#test data:

TDF <- tibble(DATE = seq( make_datetime(2007,09,23,06,00), make_datetime(2008,07,05,23,00), by = 600),
              V1 = round(runif(length(DATE)),2),
              V2 = round(runif(length(DATE)),2),
              V3 = round(runif(length(DATE)),2)
)


for (year in min( year( TDF$DATE)) : max( year( TDF$DATE))) {
  for (mon in min( month( TDF$DATE)) : max( month( TDF$DATE))) {
    for (var in c( "V1", "V2", "V3")) {
      filename <- paste0("Abb/", var, "_", year, "-", mon, "_ZR.png")
      png(filename, width = 1800, height = 900, res = 200)
      p <- ggplot( TDF[ year(TDF$DATE) == year & month(TDF$DATE) == mon,])
      p <- p + geom_line( aes_string( "DATE", paste0(var)))
      print(p)
      graphics.off()
    }
  }
}

所以,一定有更好的方法。我现在正在努力解决这个问题(相同的测试数据):

yearmonmin <- TDF$DATE %>% min() %>% floor_date(unit = "month") 
yearmonmax <- TDF$DATE %>% max() %>% ceiling_date(unit = "month")

seq(yearmonmin, yearmonmax, by = "month")

for (yearmon in seq(yearmonmin, yearmonmax, by = "month")) {
  print(var)
}

这真的让我很困惑,因为

> seq(yearmonmin, yearmonmax, by = "month")
 [1] "2007-09-01 UTC" "2007-10-01 UTC" "2007-11-01 UTC" "2007-12-01 UTC" "2008-01-01 UTC" "2008-02-01 UTC" "2008-03-01 UTC" "2008-04-01 UTC"
 [9] "2008-05-01 UTC" "2008-06-01 UTC" "2008-07-01 UTC" "2008-08-01 UTC"    

但是

> for (yearmon in seq(yearmonmin, yearmonmax, by = "month")) {
+   print(yearmon)
+ }
[1] 1188604800
[1] 1191196800
[1] 1193875200
[1] 1196467200
[1] 1199145600
[1] 1201824000
[1] 1204329600
[1] 1207008000
[1] 1209600000
[1] 1212278400
[1] 1214870400
[1] 1217548800

我已经尝试了seq.Date 和两天的其他不值得在这里展示的替代品...

我听说在 R 中最好避免循环。所以...有人吗?

【问题讨论】:

    标签: r loops date ggplot2 dplyr


    【解决方案1】:

    我们使用melt 将数据从宽到长重塑,因此我们可以将V1V2V3 作为单个列进行操作。然后我们创建月份组。我已经使用 dplyr 链接运算符 (%&gt;%) 完成了所有这些工作。

    现在我们有了所需形式的数据,我们使用lapply 为每个月的每个原始值列创建时间序列图。 split 函数将数据框拆分为每个月的单独数据框,以便我们可以为每个月的数据创建单独的图。 lapplysplit 的这种组合避免了显式循环。

    library(lubridate)
    library(ggplot2)
    library(reshape2)
    library(dplyr)
    
    # Reshape to long and add month grouping
    TDF = TDF %>% melt(id.var="DATE") %>%
      arrange(DATE) %>%
      mutate(month = paste0(month(DATE, label=TRUE, abbr=TRUE)," ", year(DATE)),
             month = factor(month, levels=unique(month)))
    
    # Create a list of plots by month
    pl = lapply(split(TDF, TDF$month), function(df) {
      ggplot(df, aes(DATE, value)) +
        geom_line(aes(group=variable)) +
        facet_grid(. ~ variable) +
      theme(axis.text.x = element_text(angle=-90, hjust=0, vjust=0.5))
    })
    

    您现在有一个列表,其中每个列表元素都包含一个月数据的图。例如:

    pl[["Sep 2007"]] 
    

    您可以将这些图保存到单独的文件中,也可以将它们放在一个页面上并保存。或者,如果您保存为 PDF,您可以创建一个多页 PDF,每页上只有一个图。

    如果您想将V1V2V3 放在单独的图中,您可以执行与上面的代码类似的操作,但对split 函数稍作更改以由month 分割和variable

    pl = lapply(split(TDF, paste(TDF$variable, TDF$month)), function(df) {
      ggplot(df, aes(DATE, value)) +
        geom_line(aes(group=variable)) +
        facet_grid(. ~ variable) +
        theme(axis.text.x = element_text(angle=-90, hjust=0, vjust=0.5))
    })
    

    现在列表的每个元素都是每个月的每个变量的单个图:

    pl[["V1 Apr 2008"]]
    

    【讨论】:

    • 哇,非常感谢您的详细回答!我有很多东西要学!第一个数字,但在彼此之上,实际上是我想要的。但首先,我必须真正了解你做了什么! ;D 谢谢!
    • 要堆叠刻面,而不是将它们并排放置,请将facet_grid(. ~ variable) + 更改为facet_grid(variable ~ .) +。如果您希望我对任何代码提供其他解释,请告诉我。
    猜你喜欢
    • 1970-01-01
    • 2012-10-17
    • 2014-03-12
    • 1970-01-01
    • 1970-01-01
    • 2013-07-07
    • 1970-01-01
    • 2014-01-10
    • 1970-01-01
    相关资源
    最近更新 更多