【问题标题】:Aggregate data by equally spaced time intervals in R在 R 中按等间隔的时间间隔聚合数据
【发布时间】:2015-06-19 07:41:12
【问题描述】:

我的数据集是这样的

Section Time  x
s3      9:35  2
s4      9:35  2
s1      9:36  1
s2     10:01  1
s8     11:00  2

所以,我想按每小时间隔对数据部分进行分组,并总结该间隔内的 x 值

我的预期输出是

 sec     Time          x
 s1      9:00-10:00    1
 s2      9:00-10:00    0
 s3      9:00-10:00    2
 s4      9:00-10:00    2
 s8      9:00-10:00    0
 s1      10.00-11.00   0
 s2      10.00-11.00   1
 s3      10.00-11.00   0
 s4      10.00-11.00   0
 s8      10.00-11.00   1   

我试图从这篇帖子 in stack overflow 中获得一些帮助,但是我的这个查询出现了以下错误。这里 x 是我的框架

data.frame(value = tapply(cbind(x$x),
                     list(sec= x$section,cut(x$Time, breaks="1 hour")),
                       sum))

Error in cut.default(x$Time, breaks = "1 hour") : 'x' must be numeric

我什至不确定这是对还是错。我从来没有在 R 中处理过时间数据。所以任何关于如何实现这一点的帮助都会非常有帮助。

【问题讨论】:

  • 只是为了确保:s1S1 相同?

标签: r time-series aggregate


【解决方案1】:

我认为问题在于您的Time 列是字符格式?

无论如何,这是一种使用 dplyr 的快速而肮脏的方法:

library(dplyr)
x <- data.frame(section = c("s3", "s4", "s1", "s2", "s8", "s1", "s2", "s3"), 
            Time = c("9:35", "9:35", "9:36", "10:01", "11:00", "9:45", "10:05", "10:05"), 
            x = c(2, 2, 1, 1, 2, 6, 2, 4), stringsAsFactors = FALSE)
x %>% 
  rowwise %>% 
  mutate(aux = as.numeric(strsplit(Time, ":")[[1]][1]),
         time = paste0(aux, ":00-", aux+1, ":00")) %>% 
  select(-aux, -Time) %>% 
  ungroup %>% 
  group_by(time, section) %>% 
  summarise(x = sum(x)) %>% 
  ungroup

【讨论】:

  • 谢谢。你是对的,问题出在时间列上。我在会话 options(stringsAsFactors = FALSE) 开始时做了类似的事情。另外,请您解释一下这段代码,以便我将来自己实现它。另外,如果有办法用基础 R 做到这一点?
  • 我想如果你看一下从Introduction 开始的 dplyr 小插曲,你会更好地理解,但我基本上是使用管道运算符 (%&gt;%) 链接操作。首先我考虑我的data.frame x,然后我告诉它对每一行执行未来的操作,然后我告诉它添加两个新列(辅助和时间),然后我删除辅助和时间列,然后我删除完成的分组按行,然后我按时间和部分分组,并对每个组求和 x。
  • 对于基本 R 解决方案,请参阅@RHertel 的答案
  • 我仍在努力改进版本。到目前为止,我的代码并没有在给定的时间范围内对相同的部分求和。今天我应该设法纠正这个问题。无论如何,我认为您的解决方案更好,@Tutuchan。我投了赞成票。
【解决方案2】:

这是一个替代版本:

m1 <- as.data.frame(matrix(c("s3","9:35",2,"s4","9:35",2,"s1","9:36",1,"s2","10:01",1,"s8","11:00",2),byrow=T,ncol=3))
colnames(m1) <- c("Section", "Time","x")
times <- as.character(m1$Time)
hours <- sapply(sapply(times,function(x)strsplit(x,":")),function(x)x[1])
small_hours <- hours[which(as.numeric(hours)<10)]
small_hours <- sapply(small_hours,function(x) paste0("0",x))
hours[which(as.numeric(hours)<10)]<-small_hours
hour_range <- sapply(hours,function(x) paste0(x,":00-",as.character(as.numeric(x)+1),":00"))
m1$Time <- hour_range
m1$x <- as.numeric(m1$x)
require (plyr)
m1 <- ddply(m1, .(Time,Section), summarise, x = sum(x))
m1 <- m1[,c("Section","Time","x")]

这给出了以下数据框:

> m1
  Section        Time x
1      s1 09:00-10:00 1
2      s3 09:00-10:00 2
3      s4 09:00-10:00 2
4      s2 10:00-11:00 1
5      s8 11:00-12:00 2

这里的技巧是,就像在@Tutuchan 的建议中一样,忽略时间实际上就像 POSIXct 对象中的时间一样,而是将它们简单地视为字符字符串。我希望这会有所帮助。

更新/编辑

正如我之前在评论中提到的,我以前的代码版本没有在相同时间范围内的相等部分中执行请求的 x 总和。这在上面发布的更新版本中得到了纠正,但我决定放弃尝试在基础 R 中完成所有这些。 最终,我使用了plyr 包。

【讨论】:

    【解决方案3】:

    另一个选项是使用类POSIXct,然后在应用于日期时间对象的函数cut 中,在参数breaks 中指定“小时”。见?cut.POSIXt

    library(dplyr)
    df <- data.frame(section= c("s3", "s4", "s1", "s2", "s8"), 
                     time = strptime(c("09:35", "09:35", "09:36", "10:01", "11:00"), "%H:%M"),
                     x = c(2, 2, 1, 1, 2))
    df2 <- df %>% 
      group_by(intervals = cut(time, breaks = "hour")) %>% 
      select(section, intervals, x)
    df2$intervals <- format(as.POSIXct(df2$intervals, "%H:%M"), "%H:%M")
    

    输出:

    >df2
    Source: local data frame [5 x 3]
    Groups: intervals
    
      section intervals x
    1      s3     09:00 2
    2      s4     09:00 2
    3      s1     09:00 1
    4      s2     10:00 1
    5      s8     11:00 2
    

    【讨论】:

      猜你喜欢
      • 2014-06-17
      • 1970-01-01
      • 1970-01-01
      • 2014-03-09
      • 2018-06-18
      • 1970-01-01
      • 1970-01-01
      • 2011-04-01
      • 1970-01-01
      相关资源
      最近更新 更多