R 按时间对数据帧进行子采样,保持第二个值的顶部

R 按时间对数据帧进行子采样,保持第二个值的顶部,r,dataframe,sample,posixct,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 20

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

以下是数据示例:

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

这里有一个额外的行,因为它只在每秒钟内获取
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), ])
  })

下面是一个基本的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), ]
                  }))

马吕斯给了我需要的线索。下面是base中的一个解决方案:

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
我怀疑我是否需要向你解释,马修。如果您想要数字类,可以使用
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 
。。。或者可以重新绑定拆分的DFRM:

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

最难的部分是你想要的

每秒顶部或之前的值

因此,将时间四舍五入并取最大的一个并不十分有效,因为如果在第二个时间的顶部有一个,那么它就会被放入错误的组中。这种方法正确地处理了这种情况

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]

只是另一个
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

多排一行没关系。如果正好是.000,这不会占据秒的顶部,但在这种情况下,我可以通过对df$time-.001(数据的分辨率为毫秒)进行操作来解决这个问题。
tail
似乎很危险,因为它可能会对不完全按时间顺序排列的数据默默地给出错误的结果。在阅读此文之前(并随后在谷歌上搜索“数字的r分数部分”),我不会想到编写
%%1
。@MatthewLundberg——然后看看刚刚编辑的版本<代码>%/%与对应的代码一样好;)很好地捕捉到了“每秒顶端或之前的值”。我错过了。
                 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
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