【问题标题】:Find first sequence episode查找第一个序列剧集
【发布时间】:2016-11-28 13:55:53
【问题描述】:

我正在尝试创建一个指示序列结束的向量。

我的数据是这样的:

   id time   var wake
1   1    1 sleep    0
2   1    2 sleep    0
3   1    3 sleep    0
4   1    4     0    0
5   1    5     0    0

我想要的是这个(想要的输出

   id time   var wake
1   1    1 sleep    0
2   1    2 sleep    0
3   1    3 sleep    0
4   1    4     0    1
5   1    5     0    0
6   1    6     0    0
7   1    7     0    0
8   1    8 sleep    0
9   1    9 sleep    0
10  1   10 sleep    0
11  2    1 sleep    0
12  2    2 sleep    0
13  2    3 sleep    0
14  2    4 sleep    0
15  2    5 sleep    0
16  2    6     0    1
17  2    7     0    0
18  2    8     0    0
19  2    9 sleep    0
20  2   10 sleep    0

我在想类似的东西

library(dplyr) 

dt$time = as.numeric(as.character(dt$time))
dt$var = ifelse(dt$var == 'sleep', 1, 0)

dt = dt %>% group_by(id) %>% 
mutate(grp = cumsum(var != lag(var, default = var[1])))

dt$wake = 0
dt$wake [dt$grp == 1] <- 1

但是,它并没有只发现第一集

数据

dt = structure(list(id = structure(c(1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 
1L, 1L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L), .Label = c("1", 
"2"), class = "factor"), time = structure(c(1L, 3L, 4L, 5L, 6L, 
 7L, 8L, 9L, 10L, 2L, 1L, 3L, 4L, 5L, 6L, 7L, 8L, 9L, 10L, 2L), .Label =     c("1", 
"10", "2", "3", "4", "5", "6", "7", "8", "9"), class = "factor"), 
var = structure(c(2L, 2L, 2L, 1L, 1L, 1L, 1L, 2L, 2L, 2L, 
2L, 2L, 2L, 2L, 2L, 1L, 1L, 1L, 2L, 2L), .Label = c("0", 
"sleep"), class = "factor")), .Names = c("id", "time", "var"
), row.names = c(NA, -20L), class = "data.frame")

【问题讨论】:

  • diff(rleid(dt$var)) 这样的东西不好吗? (使用来自data.tablerleid
  • 您能否澄清一下,如果id 具有var = c("sleep", "sleep", 0, 0, "sleep", "sleep", 0, 0),那么您是想将所有唤醒标记为wake = c(0, 0, 1, 0, 0, 0, 1, 0),还是仅标记为wake = c(0, 0, 1, 0, 0, 0, 0, 0) 中的第一个?

标签: r sequence


【解决方案1】:

通过库data.table

setDT(dt)
dt[,wake:=( c(0,diff( rleid(var) ) == 1) & var != "sleep"),by=id]

想法是获取 var (rleid) 的运行长度编码:

> dt[,rleid(var),by=id][,V1]
[1] 1 1 1 2 2 2 2 3 3 3 1 1 1 1 1 2 2 2 3 3

从睡眠到 0 时 diff +1,或从 0 到睡眠,更改组时为负(从 1 重新开始):

> diff(dt[,rleid(var),by=id][,V1])
[1]  0  0  1  0  0  0  1  0  0 -2  0  0  0  0  1  0  0  1  0

如果它是 1 并且 var 不是 sleep,则得到一个 TRUE 值(如果你将整个东西包装到 as.numeric 中,它可能是 1)。

输出:

    nrow id time   var  wake
 1:    1  1    1 sleep FALSE
 2:    2  1    2 sleep FALSE
 3:    3  1    3 sleep FALSE
 4:    4  1    4     0  TRUE
 5:    5  1    5     0 FALSE
 6:    6  1    6     0 FALSE
 7:    7  1    7     0 FALSE
 8:    8  1    8 sleep FALSE
 9:    9  1    9 sleep FALSE
10:   10  1   10 sleep FALSE
11:   11  2    1 sleep FALSE
12:   12  2    2 sleep FALSE
13:   13  2    3 sleep FALSE
14:   14  2    4 sleep FALSE
15:   15  2    5 sleep FALSE
16:   16  2    6     0  TRUE
17:   17  2    7     0 FALSE
18:   18  2    8     0 FALSE
19:   19  2    9 sleep FALSE
20:   20  2   10 sleep FALSE

【讨论】:

  • 谢谢。抱歉,我对data.table 不是很熟悉。 id 在这里如何分组?
  • 哇,抱歉,我没有按 id 分组。我在你的问题中错过了这一部分。我添加了by=id,它将通过 id 计算 rle:p
【解决方案2】:

以下内容应适用于dplyr

library(dplyr)
dt <- dt %>% group_by(id) %>%
             mutate(wake = as.integer(var == '0' & var != lag(var, default = var[1])))
##Source: local data frame [20 x 4]
##Groups: id [2]
##
##       id   time    var  wake
##   <fctr> <fctr> <fctr> <dbl>
##1       1      1  sleep     0
##2       1      2  sleep     0
##3       1      3  sleep     0
##4       1      4      0     1
##5       1      5      0     0
##6       1      6      0     0
##7       1      7      0     0
##8       1      8  sleep     0
##9       1      9  sleep     0
##10      1     10  sleep     0
##11      2      1  sleep     0
##12      2      2  sleep     0
##13      2      3  sleep     0
##14      2      4  sleep     0
##15      2      5  sleep     0
##16      2      6      0     1
##17      2      7      0     0
##18      2      8      0     0
##19      2      9  sleep     0
##20      2     10  sleep     0

varvar 中的lag 进行比较,就像OP 检测sleep0 之间的过渡(或情节)一样,但将var 需要为0 的条件添加到仅标记从sleep0 的那些转换,以使wake 成为1

【讨论】:

  • 把as.numeric换成as.integer很容易理解,as wake =as.integer(var!=lag(var,default=var[1]))
【解决方案3】:

假设您要为每个id 标记所有唤醒:

1) 没有包 请注意,如果xy 是合乎逻辑的,那么x - y &gt; 0 iff xTRUEyFALSE。因此,我们有以下不使用任何包的内容:

transform(dt, wake = ave(var == 0, id, FUN = function(x) c(0, diff(x) > 0)))

2) dplyr 或者,它可以这样写成 dplyr:

library(dplyr)
dt %>% group_by(id) %>% mutate(wake = c(0, diff(var == 0) > 0)) %>% ungroup()

3) zoo 我们可以使用rollapplyr 沿着每个id 寻找序列 c(FALSE, TRUE)var==0。添加0 可确保结果为数字。

library(zoo)
roll <- function(x) rollapplyr(x, 2, identical, c(FALSE, TRUE), fill = 0)
transform(dt, wake = ave(var == 0, id, FUN = roll) + 0)

注意:如果您只想标记每个id 的第一次觉醒,并且如果out 是上述任何一项的结果,那么:

transform(out, wake = ave(wake, id, FUN = function(x) replace(0*x, which.max(x), max(x))))

【讨论】:

    【解决方案4】:

    这样做的一个丑陋的方法可能是用第 i:th 值减去第 i:th +1 以查看睡眠是否结束,如下所示:

    vec<-ifelse(dt$var=="sleep",1,0) #creating a vector for sleeping/not sleeping
    tg<-c(0,vec[1:(length(vec)-1)])-vec #if values are == 1, i.e. first episode of not sleeping
    

    那么您可以编写以下代码来获取wake

    ifelse(tg==1,1,0)  [1] 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0
    

    编辑:感谢下面的 cmets,我更新了我的答案。

    vec<-ifelse(dt$var=="sleep",1,0)
    
    lapply(unique(dt$id), function(x) ifelse(c(0,vec[min(which(dt$id==x)):(max(which(dt$id==x))-1)])-vec[dt$id==x]==1,1,0))
    

    【讨论】:

      【解决方案5】:

      不是很优雅,但这可以完成工作。 确保事先按 id 和时间对 dt 进行排序。

      dt$id <- as.character(dt$id)
      dt$time <- as.integer(as.character(dt$time))
      dt$var <- as.character(dt$var)
      dt <- dplyr::arrange(dt, id, time)
      dt$wake <- 0
      dt$wake[which(dt$var == "0" & lag(dt$var) == "sleep" & 
                      dt$id == lag(dt$id))] <- 1
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2019-04-23
        • 1970-01-01
        • 2019-08-12
        • 2023-03-25
        • 2012-08-18
        • 1970-01-01
        • 2015-02-01
        相关资源
        最近更新 更多