2

小数秒のタイムスタンプを含むデータ フレームがあります。1 秒あたり複数の行があり、1 行に絞り込みたいと考えています。各秒の先頭またはその直前の値を抽出したい。

データの例を次に示します。

 > head(sg1, 13)
                      time  count
1  2013-02-25 15:55:35.941      0
2  2013-02-25 15:55:36.042   8263
3  2013-02-25 15:55:36.144 147536
4  2013-02-25 15:55:36.243 165041
5  2013-02-25 15:55:36.342 126064
6  2013-02-25 15:55:36.441 100275
7  2013-02-25 15:55:36.542 101944
8  2013-02-25 15:55:36.647 108880
9  2013-02-25 15:55:36.742  86690
10 2013-02-25 15:55:36.842  74476
11 2013-02-25 15:55:36.941  76285
12 2013-02-25 15:55:37.042  79145
13 2013-02-25 15:55:37.141  84434

このうち、1 行目と 11 行目を選択したいと思います。

> dput(head(sg1, 13))
structure(list(time = structure(c(1361807735.942, 1361807736.042, 
1361807736.145, 1361807736.244, 1361807736.343, 1361807736.442, 
1361807736.542, 1361807736.647, 1361807736.742, 1361807736.842, 
1361807736.942, 1361807737.042, 1361807737.142), class = c("POSIXct", 
"POSIXt"), tzone = "GMT"), count = c(0L, 8263L, 147536L, 165041L, 
126064L, 100275L, 101944L, 108880L, 86690L, 74476L, 76285L, 79145L, 
84434L)), .Names = c("time", "count"), row.names = c(NA, 13L), class = "data.frame")
4

6 に答える 6

4

難しい部分は、あなたが欲しいということです

各秒の先頭またはその直前の値。

そのため、時間を切り捨てて最大のものを取得してもうまくいきません。2 番目の先頭に 1 つあると、間違ったグループに入れられてしまうからです。このアプローチは、そのケースを正しく処理します。

library("lubridate")
library("plyr")
ddply(sg1, .(ceiling_date(time, unit="second")), function(DF) {
  DF[which.max(DF$time - ceiling_date(DF$time)),]
})[,-1]

を与える

                 time count
1 2013-02-25 15:55:35     0
2 2013-02-25 15:55:36 76285
3 2013-02-25 15:55:37 84434

これがラウンド秒で機能することを示すために、データ セットに 1 を追加します。

sg2 <- rbind(sg1, 
structure(list(time=structure(1361807737, class=c("POSIXct", "POSIXt"), 
tzone="GMT"), count=c(34567L)), .Names = c("time", "count"), row.names=c(NA,1L),
class="data.frame"))
sg2 <- sg2[order(sg2$time),]

ddply(sg2, .(ceiling_date(time, unit="second")), function(DF) {
  DF[which.max(DF$time - ceiling_date(DF$time)),]
})[,-1]

「前の」秒の新しい行を返すようになりました。

                 time count
1 2013-02-25 15:55:35     0
2 2013-02-25 15:55:37 34567
3 2013-02-25 15:55:37 84434
于 2013-03-11T22:01:42.670 に答える
3
tapply(rownames(sg1), format(sg1$time, "%Y-%m-%d %M:%S"), tail, 1)
2013-02-25 55:35 2013-02-25 55:36 2013-02-25 55:37 
             "1"             "11"             "13" 

これをあなたに説明する必要はないと思います、マシュー。数値クラスが必要な場合は、1:nrow(sg1)行名の代わりに使用できます。(ああ、投稿した後、私はあなたが覚えているのを見ますtail。)

行全体が必要なように見えるので、これを sg1 へのインデックスとして使用します。

> sg1[ tapply(rownames(sg1), format(sg1$time, "%Y-%m-%d %M:%S"), tail, 1) , ]
                  time count
1  2013-02-25 15:55:35     0
11 2013-02-25 15:55:36 76285
13 2013-02-25 15:55:37 84434 

... または、分割された dfrms を rbind することもできます:

> do.call(rbind, lapply(split(sg1, format(sg1$time, "%Y-%m-%d %M:%S")), tail, 1) )
                                time count
2013-02-25 55:35 2013-02-25 15:55:35     0
2013-02-25 55:36 2013-02-25 15:55:36 76285
2013-02-25 55:37 2013-02-25 15:55:37 84434

...おそらくもっと「標準的なR」です。

于 2013-03-11T21:59:11.693 に答える
1

max(time)これは 1 秒ごとに を取得するだけなので、余分な行がありますが、次のようになります。

library(lubridate)
df$second = floor(second(df$time))

library(plyr)
top_seconds = ddply(
  df,
  .(second),
  function(df_part) {
    return(df_part[df_part$time == max(df_part$time), ])
  })
于 2013-03-11T21:41:10.570 に答える
1

ちょうど別のbase解決策

sg1[sg1$time %in% aggregate(sg1$time, 
                            by = list(ceiling(as.numeric(sg1$time))), 
                            FUN = max)$x, ]
##                   time count
## 1  2013-02-25 15:55:35     0
## 11 2013-02-25 15:55:36 76285
## 13 2013-02-25 15:55:37 84434
于 2013-03-12T00:53:36.027 に答える
1

基本的な R ソリューションは次のとおりです。

do.call(rbind, by(data = sg1, 
                  INDICES = as.numeric(sg1$time) %/% 1,
                  FUN = function(X) {
                      X[which.max(as.numeric(X$time) %% 1), ]
                  }))
#                                      time count
# 2013-02-25-:55:35 2013-02-25 15:55:35.941     0
# 2013-02-25-:55:36 2013-02-25 15:55:36.941 76285
# 2013-02-25-:55:37 2013-02-25 15:55:37.141 84434

Brian Diggs が推測するように、同じ秒に 15:55:36.941 と 15:55:37.000 を含めたい場合は、両方が存在する場合は後者を保持します。これを試してください。

do.call(rbind, by(data = sg2, 
                  INDICES = ceiling(as.numeric(sg2$time)),
                  FUN = function(X) {
                      X[which.max(as.numeric(X$time) %% -1), ]
                  }))
于 2013-03-11T21:55:02.430 に答える
1

マリウスは私が必要としていた手がかりを教えてくれます。ベースのソリューションは次のとおりです。

do.call(rbind, unname(by(sg1, floor(as.numeric(sg1$time)), FUN=tail, 1)))
                      time count
1  2013-02-25 15:55:35.941     0
11 2013-02-25 15:55:36.941 76285
13 2013-02-25 15:55:37.141 84434
于 2013-03-11T21:55:33.823 に答える