按时间子采样子数据,保持第二个值的顶部

时间:2013-03-11 21:31:45

标签: r dataframe sample posixct

我有一个包含带小数秒的时间戳的数据框。每秒有多行,我想过滤到一行。我想在每秒的顶部或之前提取值。

以下是数据示例:

 > 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")

6 个答案:

答案 0 :(得分:4)

困难的部分是你想要的

  

每秒顶部或之前的值。

因此,缩小时间并取出最大的时间并不是很有效,因为如果在第二个顶部有一个,那么它会被放入错误的组中。这种方法正确处理了这种情况。

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

为了证明这适用于圆秒,请在数据集中添加一个。

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

答案 1 :(得分: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)而不是rownames。 (哦,发帖后我看到你记得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:

> 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”。

答案 2 :(得分:1)

那里有一个额外的行,因为这只会在每秒内抓住max(time),但是:

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), ])
  })

答案 3 :(得分: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), ]
                  }))

答案 4 :(得分: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

答案 5 :(得分: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