【问题标题】:1s data to 10 minute statistics using timestamp使用时间戳的 1s 数据到 10 分钟统计
【发布时间】:2015-11-08 01:12:26
【问题描述】:

我每秒测量一次风速和风向。我需要将数据减少到 10 分钟的平均值,同时保存最小值、最大值和 sd 值。

10 分钟的块应该有特定的时间间隔,例如在时间 10:10 和 10:20 之间应该在新的 data.frame 中有时间戳 10:20。 有时测量中存在间隙,因此应丢弃少于 600 次测量的 10' 周期。 以下是输入数据框的样子:

     date        time    speed        angle
1 2015-02-24 10:33:20.00 7.415 -17.65045166
2 2015-02-24 10:33:21.00 6.650   0.06921746
3 2015-02-24 10:33:22.00 6.650 -19.54238892
4 2015-02-24 10:33:23.00 7.415 -46.76791382
5 2015-02-24 10:33:24.00 6.650  84.60681152
6 2015-02-24 10:33:25.00 6.650   7.41780472

这是它最后应该看到的:

    date        time    speedAvg angleAvg  speedMax speedMin speedSd
1 2015-02-24 10:30:00 
2 2015-02-24 10:40:00 
3 2015-02-24 10:50:00 
4 2015-02-24 11:00:00 
5 2015-02-24 11:10:00 
6 2015-02-24 11:20:00

所以,我认为这样做的方法是使用日期时间变量上的函数子集来创建可用于计算值的数据框。在循环结束时使用 rbind。 我不知道如何在特定时间间隔内使用子集。 此外,欢迎就更优雅的解决方案提出建议。

【问题讨论】:

  • 似乎我无法编辑自己的问题...:-/ 我忘了提到我正在使用 R。我不允许给出更具体的标签,因为我没有有制作新标签的声誉。

标签: r average subset


【解决方案1】:

我是这样处理的:

  1. 使用所有 1 秒的时间戳构建时间序列“X”,即没有间隙。
  2. 从数据框“data”中填写测量值。
  3. 使用时间序列“X”中的数据计算 10 分钟统计数据并将结果写入新的时间序列“Y”。
  4. 从“Y”中删除缺少某些数据的行。

.

library(timeDate)
library(timeSeries)

data <- read.table( filename, header=TRUE )

########################################################################
# Build a timeSeries "X" from the data.frame "data":

tm <- as.timeDate( strptime(paste(as.character(data$date),as.character(data$time)),
                            format="%Y-%m-%d %H:%M:%S.00",
                            tz = "GMT"),
                   zone = "GMT")

t <- timeSequence(start(tm),end(tm),by="secs")

X <- timeSeries( data.frame( speed = rep(NA,length(t)),
                             angle = rep(NA,length(t)) ) )

setTime(X) <- t

X[tm]$speed <- data$speed
X[tm]$angle <- data$angle

#----------------------------------------------------------------
# Restrict the timestamps to 10 minute steps:

m <- seq( from = which.max(format(t[601:length(t)],"%M:%S")=="00:00"),
          to   = length(t),
          by   = 600      )

#----------------------------------------------------------------
# Calculate 10 minute statistics:

Y <- timeSeries( data.frame(
  speed_avg = sapply(m,function(m){mean(na.omit(X$speed[(m-599):m]))}),
  speed_sd  = sapply(m,function(m){sd(na.omit(X$speed[(m-599):m]))}),
  speed_min = sapply(m,function(m){min(na.omit(c(X$speed[(m-599):m],Inf)))}),
  speed_max = sapply(m,function(m){max(na.omit(c(X$speed[(m-599):m],-Inf)))}),
  angle_avg = sapply(m,function(m){mean(na.omit(X$angle[(m-599):m]))}) ) )

setTime(Y) <- t[m]
Y <- Y[complete.cases(Y),]

write.table(Y,filename_10min)

由于需要大量数据,我使用以下脚本创建示例数据:

library(timeDate)

#######################################################################
# Create example data

set.seed(1)

t_start <- as.timeDate("2015-01-01 00:00:00")
t_end   <- as.timeDate("2015-01-03 13:00:00")

t <- timeSequence(t_start,t_end,by="sec")

data <- data.frame( date  = format(t,"%Y-%m-%d"),
                    time  = format(t,"%H:%M:%S.00"),
                    speed = 6 + sin((1:length(t))/500) + sample(-10:10,length(t),replace=TRUE)/15,
                    angle = sample(-900:900,length(t),replace=TRUE)/10 )

# Some values are missing:
data[8823:11580,] <- NA
data[13585:18801,] <- NA
data[sample(1:nrow(data),0.1*nrow(data)),] <- NA
data <- na.omit(data)

write.table( data, filename, quote=FALSE, row.names=FALSE )

【讨论】:

    【解决方案2】:

    您可以通过执行以下操作使用 dplyr 轻松完成此操作:

    1. 在数据框中创建一个新列,每行的开始时间间隔为 10 分钟(小时和分钟)。
    2. 使用 dplyr 函数轻松聚合数据并过滤掉数据少于 600 个时间点的行。 here is a quick intro to dplyr 假设您的数据存储在一个名为 X 的对象中:

    library(dplyr)
    X$time <- as.character(X$time)
    X$hourmin <- substr(X$time, 1, 4)
    X$time <- paste(X$hourmin, "0:00", sep = "")
    X <- X %>% group_by(date, time)
           %>% summarize(
               speedAvg = mean(speed, na.rm=T)
              ,angleAvg = mean(angle, na.rm=T)
              ,speedMax = max(speed, na.rm=T)
              ,speedMin = min(speed, na.rm=T)
              ,speedSd = sd(speed, na.rm=T)
              ,datapoint_count = n())
      %>% filter(datapoint_count >= 600))
    
    #remove datapoint_count column.
    X <- X[, -8]
    

    【讨论】:

    • @mra68 为什么 data_point > 0,他确实说过他想丢弃少于 600 次观察的 10 分钟间隔,因此 data_point >= 600。data_point 计算每 10 分钟间隔内的观察总数.
    • 恐怕用“data_point>=600”几乎什么都不会存活。如果只缺少 1 秒,也没有充分的理由在 10 分钟内扔掉这个洞。
    • 是否有任何东西能幸存下来,不在这个问题的范围内。您可以与@GeorgeLongIsland 讨论分析的细节,因为他选择通过丢弃它们来估算他的缺失。
    • 我实现了这个解决方案,并通过细微的更改来避免覆盖列(这样我可以看到发生了什么)。是的,我将最低要求降低到 400 个数据点以保留更多数据:)
    • 很高兴它成功了。您可以单击绿色复选标记将其标记为答案,以便其他人在遇到类似问题时知道要查看哪个答案。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2019-03-03
    • 2020-08-20
    • 1970-01-01
    • 2016-04-15
    • 2017-09-04
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多