我有一个包含带小数秒的时间戳的数据框。每秒有多行,我想过滤到一行。我想在每秒的顶部或之前提取值。
以下是数据示例:
> 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")
答案 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