【问题标题】:create counter variable with Boolean condition using value from the previous row使用上一行中的值创建具有布尔条件的计数器变量
【发布时间】:2016-07-25 03:49:00
【问题描述】:

我想根据 变量用户真假创建一个计数器变量c 变量B。

DT <- data.table(time=c(1,2,3,1,1,2,3,1,1,1),user=c(1,1,1,2,3,3,3,4,4,5), B=c('t','f','t','f','f','t','t','t','t','t'))
DT

变量c的期望输出

    time user B C
 1:    1    1 t 1
 2:    2    1 f 1
 3:    3    1 t 2
 4:    1    2 f 0
 5:    1    3 f 0
 6:    2    3 t 1
 7:    3    3 t 2
 8:    1    4 t 1 
 9:    2    4 t 2
10:    1    5 t 1

当 B 为真时,变量 c 是组内的计数器。 变量c的逻辑(非代码)如下。从时间变量中可以看出,顺序确实很重要。

 if time=1 and b=='f' {c=0}
    else 
    {
      if b=='t'{c=previous[c]+1} 
      else {c=previous[c]}
    }


  #if there is no variable b, the counter can be created using dplyr:     
          group_by(user)%>%mutate(c=seq_along(user))
  #or data.table
         DT[, c := seq_len(.N), by = user]
  # we can use data.table function shift() combined with for loop but i want to avoid for loop, it is slow and I have 300,000 rows.

【问题讨论】:

  • 您应该将 B 存储为逻辑向量,而不是使用您自己的真假代码。试试DT[, B := B == "t"]
  • 我对你的代码有点迷茫。您将 B 存储为逻辑,对吗?@Frank
  • 代码用classlogical 覆盖您的B 列。如果您不清楚我的意思,请阅读 ?class?logical 的文档。
  • “在每组用户中创建一个 B==True 的累积计数器”

标签: r data.table dplyr


【解决方案1】:

我们按“用户”、cumsum 逻辑向量 (B=="t") 分组,并将输出分配 (:=) 给“C”。

DT[, C:= cumsum(B=="t"), by = user]
DT
#    time user B C
# 1:    1    1 t 1
# 2:    2    1 f 1
# 3:    3    1 t 2
# 4:    1    2 f 0
# 5:    1    3 f 0
# 6:    2    3 t 1
# 7:    3    3 t 2
# 8:    1    4 t 1
# 9:    2    4 t 2
#10:    1    5 t 1

同样的逻辑可以应用于dplyr方法

library(dplyr)
DT %>%
   group_by(user) %>%
   mutate(C = cumsum(B == "t"))

【讨论】:

  • 有没有办法合并shift(),在今天,代码会更通用?
  • @Phdami 如果你需要shift'C'栏,DT[, paste0("Clag", 1:2) := shift(C, 1:2), by = user]
  • 嗨,我需要在不同条件下大量使用前一行的值。我只是想知道,是否有办法使用前一行的值来创建计数器而不是 cumsum。非常感谢!
  • @Phdami 我不确定我是否理解您的问题。你能把它作为一个新问题发布吗?
  • 我已经更新了问题。如果某些行的时间变量相同怎么办(这并不意味着行是重复的,因为它可能有其他列不同,但我没有在这里显示。)
【解决方案2】:

如果你使用 for 循环来做同样的事情,下面逻辑的语法是

for(i in unique(DT$user)){
  DT$c[DT$user==i] <- cumsum(DT$B[DT$user==i]=="t")
}

print(DT)

  time user B c
 1:    1    1 t 1
 2:    2    1 f 1
 3:    3    1 t 2
 4:    1    2 f 0
 5:    1    3 f 0
 6:    2    3 t 1
 7:    3    3 t 2
 8:    1    4 t 1
 9:    2    4 t 2
10:    1    5 t 1

【讨论】:

  • 为什么要将数字列初始化为“”(字符串)?
  • data.table 中的 for 循环快吗?还是和 r.base 一样的速度?我的数据中有超过 300,000 行。
  • @Phdaml 使用基函数可以加快速度,而不是使用 for 循环
  • @Arunkumarmahesh 我不明白。使用基函数可以加快速度而不是 for 循环是什么意思?您正在使用 for 循环,对吗?当您在 data.table 中使用 for 循环而不是 data.frame 时,在速度方面有什么不同吗?
  • @Phdaml 当我们使用 data.table 时,经过的速度是 0.03 秒,而在 data.frame 中,经过的速度是 0.00 秒,所以使用 data.frame 比使用 data.table 好
猜你喜欢
  • 1970-01-01
  • 2021-07-14
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-12-18
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多