【问题标题】:Subset R dataframe by factor level, removing ALL rows after threshold crossed the FIRST time按因子级别子集 R 数据帧,在阈值超过第一次后删除所有行
【发布时间】:2017-07-16 14:47:16
【问题描述】:

我有一些网络会话数据,我试图在上次访问过去一段时间(比如说 10 天)后排除所有观察结果。我有一个 ID、一个 VisitNum 和一个计算的 DateDiff,表示自上次访问以来经过的天数。我的 ID 是因素,因此我需要解决方案来处理多个因素水平。

样本数据:

test_data <- data.frame(ID=c("abc123","abc123","abc123","abc123"),
                    VisitNum=c(1,2,3,4),
                    DateDiff=c(0,5,30,5))

由于第 3 次访问发生在第 2 次访问后 30 天,我想从数据框中排除第 3 次和第 4 次访问。我提出的解决方案将排除第 3 次访问,但保留第 4 次访问 - 这不是我需要的。

我想要的结果是这样的:

test_results <- data.frame(ID=c("abc123","abc123"),
                       VisitNum=c(1,2),
                       DateDiff=c(0,5))

谢谢!

【问题讨论】:

  • 关于如何在 R 中编码/操作数据的问题不在此处讨论。这将在Stack Overflow 上讨论。如果您等待,我们将尝试为您迁移。
  • 谢谢@gung,很抱歉我已经有一段时间没有使用这些论坛了。

标签: r time-series subset date-arithmetic


【解决方案1】:

对于这个例子,你可以使用基本的R函数cummin

test_data[as.logical(cummin(test_data$DateDiff < 10)), ]
      ID VisitNum DateDiff
1 abc123        1        0
2 abc123        2        5

将此应用于多个 ID 时,可以使用基本 R 函数ave

test_data[as.logical(ave(test_data$DateDiff, test_data$ID,
                         FUN=function(i) cummin(i < 10))), ]
      ID VisitNum DateDiff
1 abc123        1        0
2 abc123        2        5
6 abc323        2        5
7 abc323        3        5

这里使用as.logical是因为我们依赖于逻辑子估计,ave返回初始向量的模式。


data.table 中的等效操作是

library(data.table
setDT(data.table)
test_data[as.logical(test_data[,cummin(DateDiff < 10), by=ID]$V1)]

数据

test_data <- 
structure(list(ID = structure(c(1L, 1L, 1L, 1L, 2L, 3L, 3L),
.Label = c("abc123", "abc223", "abc323"), class = "factor"),
VisitNum = c(1, 2, 3, 4, 2, 2, 3), DateDiff = c(0, 5, 30, 5, 20, 5, 5)),
Names = c("ID", "VisitNum", "DateDiff"), row.names = c(NA, -7L),
class = "data.frame")

【讨论】:

  • 出色的工作@lmo,完美运行。非常感谢您的贡献!
  • 谢谢。 cummin 经常被忽视,但在这些类型的情况下非常有用。
【解决方案2】:

您也可以使用which

test_data[1:(which(test_data$DateDiff > 10)[1] - 1),]

对于较大的数据集,这似乎要快一些

test_data <- data.frame(ID=sample(c("abc123","abc123","abc123","abc123"),2000,T),
                        VisitNum=1:2000,
                        DateDiff=sample(c(0,5,30,5),2000,T))

a <- function(dat) dat[1:(which(dat$DateDiff > 10)[1] - 1),]
b <- function(dat) dat[as.logical(cummin(dat$DateDiff < 10)), ]
microbenchmark(a(test_data), b(test_data), times = 1000)

## Unit: microseconds
##          expr     min       lq     mean  median      uq        max neval cld
##  a(test_data) 141.198 146.1895 197.6538 151.507 167.880   2326.238  1000  a 
##  b(test_data) 196.443 201.4810 496.1748 209.448 235.708 137785.448  1000   b

对于一个包含 2000 行的数据集,函数 b 执行 1000 次后的中位执行时间增加了约 38%。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2017-11-26
    • 2014-02-11
    • 2012-06-23
    • 1970-01-01
    • 1970-01-01
    • 2018-01-31
    • 2017-02-13
    相关资源
    最近更新 更多