web-dev-qa-db-ja.com

Rの分単位のデータから15分の時間間隔を作成しますか?

次のようにフォーマットされたデータがあります。

time     count 
00:00    17
00:01    62
00:02    41

だから私は00:00から23:59時間まで、毎分カウンターを持っています。次のように15分間隔でデータをグループ化したいと思います。

time           count
00:00-00:15    148   
00:16-00:30    284

手動でやろうとしたのですが、疲れ果ててしまうので、簡単にやるには関数かsthが必要だと思いますが、どうしたらいいのかまだわかりません。

助けていただければ幸いです!!

どうもありがとうございました!

12
adrian1121

POSIXct形式のデータの場合、cut関数を使用して15分のグループを作成し、それらのグループごとに集計できます。以下のコードは、_base R_で、およびdplyrおよび_data.table_パッケージを使用してこれを行う方法を示しています。

まず、いくつかの偽のデータを作成します。

_set.seed(4984)
dat = data.frame(time=seq(as.POSIXct("2016-05-01"), as.POSIXct("2016-05-01") + 60*99, by=60),
                 count=sample(1:50, 100, replace=TRUE))
_

ベースR

cutデータを15分のグループに分けます:

_dat$by15 = cut(dat$time, breaks="15 min")
_
_                   time count                by15
1   2016-05-01 00:00:00    22 2016-05-01 00:00:00
2   2016-05-01 00:01:00    11 2016-05-01 00:00:00
3   2016-05-01 00:02:00    31 2016-05-01 00:00:00
...
98  2016-05-01 01:37:00    20 2016-05-01 01:30:00
99  2016-05-01 01:38:00    29 2016-05-01 01:30:00
100 2016-05-01 01:39:00    37 2016-05-01 01:30:00
_

集計関数としてaggregateを使用して、新しいグループ化列でsumを実行します。

_dat.summary = aggregate(count ~ by15, FUN=sum, data=dat)
_
_                 by15 count
1 2016-05-01 00:00:00   312
2 2016-05-01 00:15:00   395
3 2016-05-01 00:30:00   341
4 2016-05-01 00:45:00   318
5 2016-05-01 01:00:00   349
6 2016-05-01 01:15:00   397
7 2016-05-01 01:30:00   341
_

dplyr

_library(dplyr)

dat.summary = dat %>% group_by(by15=cut(time, "15 min")) %>%
  summarise(count=sum(count))
_

data.table

_library(data.table)

dat.summary = setDT(dat)[ , list(count=sum(count)), by=cut(time, "15 min")]
_

PDATE:コメントに答えるために、この場合、各グループ化間隔の終点はas.POSIXct(as.character(dat$by15)) + 60*15 - 1です。つまり、グループ化間隔の終点は、間隔の開始から15分マイナス1秒です。 POSIXctは秒単位であるため、60 * 15-1を追加します。 as.POSIXct(as.character(...))は、cutが因数を返し、これがそれを日時に変換して計算できるようにするためです。

終点を(最も近い秒ではなく)次の間隔の前の最も近い分にしたい場合は、as.POSIXct(as.character(dat$by15)) + 60*14を実行できます。

たとえば、休憩の数を選択し、Rに間隔を選択させたために休憩の間隔がわからない場合は、max(unique(diff(as.POSIXct(as.character(dat$by15))))) - 1を実行して追加する秒数を見つけることができます。

16
eipi10

カットアプローチは便利ですが、大きなデータフレームでは時間がかかります。次のアプローチは、カットアプローチ(400kレコードでテスト済み)よりも約1,000倍高速です。

  #     Function: Truncate (floor) POSIXct to time interval (specified in seconds)
  #       Author: Stephen McDaniel @ PowerTrip Analytics
  #        Date : 2017MAY
  #    Copyright: (C) 2017 by Freakalytics, LLC
  #      License: MIT

  floor_datetime <- function(date_var, floor_seconds = 60, 
        Origin = "1970-01-01") { # defaults to minute rounding
     if(!is(date_var, "POSIXct")) stop("Please pass in a POSIXct variable")
     if(is.na(date_var)) return(as.POSIXct(NA)) else {
        return(as.POSIXct(floor(as.numeric(date_var) / 
           (floor_seconds))*(floor_seconds), Origin = Origin))
     }
  }

サンプル出力:

test <- data.frame(good = as.POSIXct(Sys.time()), 
   bad1 = as.Date(Sys.time()),
   bad2 = as.POSIXct(NA))

test$good_15 <- floor_datetime(test$good, 15 * 60)
test$bad1_15 <- floor_datetime(test$bad1, 15 * 60)
Error in floor_datetime(test$bad, 15 * 60) : 
  Please pass in a POSIXct variable
test$bad2_15 <- floor_datetime(test$bad2, 15 * 60)

test

                        good       bad1 bad2             good_15 bad2_15
    1 2017-05-06 13:55:34.48 2017-05-06 <NA> 2007-05-06 13:45:00    <NA>
0