【问题标题】:Ozone time series臭氧时间序列
【发布时间】:2019-01-04 22:22:01
【问题描述】:

我正在处理 4 个月内环境空气中臭氧浓度的持续测量时间序列。每 5 分 14 秒进行一次测量。大约 40000 个数据点。

我开始在 R 中处理我的数据,但由于我缺乏技能而遇到了一些问题。

我的 data.frame 是 Date 作为字符和臭氧浓度作为数值。

     Date                     O3_ppb
   2018-05-26 17:55:58 UTC    33.95161
   2018-05-26 18:01:12 UTC    35.12605 
   2018-05-26 18:06:28 UTC    36.03172 
   2018-05-26 18:11:42 UTC    36.81590
   2018-05-26 18:16:57 UTC    37.11235 
   2018-05-26 18:22:12 UTC    37.26945

我想根据一个月的数据来说明 24 小时内臭氧浓度的每日变化。这意味着我希望在 24 小时内每 5 分钟平均每月一次。

我的想法是,我需要在 24 小时内每 5 分钟将我的数据分组。例如 00:00:00、00:05:00、00:10:00 … 但由于测量存在漂移,因此在一天的 00:05:00 进行的测量将在第二天的 00:06:20 进行,依此类推。而且由于传感器在重新启动时一次,因此每天的观察次数也会有所波动。

我的问题: 是否有一个函数或循环能够将我的数据分类为 5 分钟的间隔,也可以将漂移考虑在内,因此例如介于 00:02:30 - 00:07:30 之间的测量值将是分到一个称为 00:05:00 的组和 00:07:30 – 00:12:30 分到一个 00:10:00 组?

对不起,如果这完全无法理解,但我是 R 和一般编程的新手。我真的希望有人可以帮助我,所以我可以启动这个项目

【问题讨论】:

标签: r date datetime


【解决方案1】:

这是使用重叠连接 (foverlaps()) 的 data.table 方法

library( data.table )

dt <- fread(' Date                     O3_ppb
            "2018-05-26 17:55:58"    33.95161
            "2018-05-26 18:01:12"    35.12605 
            "2018-05-26 18:06:28"    36.03172 
            "2018-05-26 18:11:42"    36.81590
            "2018-05-26 18:16:57"    37.11235 
            "2018-05-26 18:22:12"    37.26945', header = TRUE)

#set to posix
dt[, Date := as.POSIXct( Date, format = "%Y-%m-%d %H:%M:%S", tz = "UTC") ]
#create dummy variables to join on later
dt[, `:=`( Start = Date, Stop = Date ) ]

#create data.table with periods you wish to summarise on later
#notice the +/- 150 (=00:02:30) to set a 5 minute 'bandwidth' around the period.
dt.period <- data.table( period = seq( as.POSIXct( "2018-05-26 00:00:00", format = "%Y-%m-%d %H:%M:%S", tz = "UTC" ),
                                  as.POSIXct( "2018-05-27 00:00:00", format = "%Y-%m-%d %H:%M:%S", tz = "UTC" ),
                                  by = "5 mins"),
                         Start = seq( as.POSIXct( "2018-05-26 00:00:00", format = "%Y-%m-%d %H:%M:%S", tz = "UTC" ) - 150,
                                      as.POSIXct( "2018-05-27 00:00:00", format = "%Y-%m-%d %H:%M:%S", tz = "UTC" ) - 150 ,
                                      by = "5 mins"),
                         Stop = seq( as.POSIXct( "2018-05-26 00:00:00", format = "%Y-%m-%d %H:%M:%S", tz = "UTC" ) + 150,
                                     as.POSIXct( "2018-05-27 00:00:00", format = "%Y-%m-%d %H:%M:%S", tz = "UTC" ) + 150,
                                     by = "5 mins") )

#perform overlap join
#first set keys
setkey(dt.period, Start, Stop)
#then perform join
result <- foverlaps( dt, dt.period, type = "within", nomatch = NA )
#summarise
result[, .( O3_ppb_avg = mean( O3_ppb, na.rm = TRUE ) ), by = .(period) ]

输出

#                 period O3_ppb_avg
# 1: 2018-05-26 17:55:00   33.95161
# 2: 2018-05-26 18:00:00   35.12605
# 3: 2018-05-26 18:05:00   36.03172
# 4: 2018-05-26 18:10:00   36.81590
# 5: 2018-05-26 18:15:00   37.11235
# 6: 2018-05-26 18:20:00   37.26945

【讨论】:

  • 非常感谢,非常感谢您花时间来做这件事。我刚刚遇到了另一个问题。每当臭氧浓度与指定的时间间隔不匹配时,它就会删除该点。是否可以在代码中添加一些内容,因此每当日期遇到不合适的臭氧浓度时,它会添加一个具有 NA 值的新行?所以最终每天都有完全相同的时间间隔。
  • 由于foverlaps() 中的nomatch = NA,不应该删除未找到的@MSM 句点...确保在执行foverlaps 后直接检查result 以使确保它们没有被删除。
【解决方案2】:

这是一种使用 lubridate 的方法,它只舍入到最接近的 5 分钟,无论时间如何。

# Load data
library(tidyverse); library(lubridate)
df <- read.table(header = T, stringsAsFactors = F,
text = "Date                     O3_ppb
   '2018-05-26 17:55:58 UTC'    33.95161
   '2018-05-26 18:01:12 UTC'    35.12605 
   '2018-05-26 18:06:28 UTC'    36.03172 
   '2018-05-26 18:11:42 UTC'    36.81590
   '2018-05-26 18:16:57 UTC'    37.11235 
   '2018-05-26 18:22:12 UTC'    37.26945") %>%
  mutate(Date = ymd_hms(Date))


df2 <- df %>%
     # By adding 2.5 min = 150 sec and rounding down, we get closest 5 min
     mutate(Date_rnd = floor_date(Date + 150, "5 minutes"),

     # One option is to group by decimal time of day 
     group    = hour(Date_rnd) + minute(Date_rnd)/60,

     # ...or could convert that to a time on a single day, in this case today
     group_as_datetime = floor_date(Sys.time(), "1 day") + group*60*60)

输出

> df2
#                 Date   O3_ppb            Date_rnd    group   group_as_datetime
#1 2018-05-26 17:55:58 33.95161 2018-05-26 17:55:00 17.91667 2019-01-05 17:55:00
#2 2018-05-26 18:01:12 35.12605 2018-05-26 18:00:00 18.00000 2019-01-05 18:00:00
#3 2018-05-26 18:06:28 36.03172 2018-05-26 18:05:00 18.08333 2019-01-05 18:05:00
#4 2018-05-26 18:11:42 36.81590 2018-05-26 18:10:00 18.16667 2019-01-05 18:10:00
#5 2018-05-26 18:16:57 37.11235 2018-05-26 18:15:00 18.25000 2019-01-05 18:15:00
#6 2018-05-26 18:22:12 37.26945 2018-05-26 18:20:00 18.33333 2019-01-05 18:20:00

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2021-08-23
    • 2016-11-10
    • 1970-01-01
    • 1970-01-01
    • 2021-02-14
    • 1970-01-01
    • 1970-01-01
    • 2011-04-14
    相关资源
    最近更新 更多