2

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

以下是数据示例:

 > 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

困难的部分是你想要

每秒顶部或之前的值。

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

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
于 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 

...或者可以 rbind 拆分的 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”。

于 2013-03-11T21:59:11.693 回答
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), ])
  })
于 2013-03-11T21:41:10.570 回答
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

马吕斯给了我我需要的线索。这是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
于 2013-03-11T21:55:33.823 回答
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 回答