2016-11-28 50 views
2

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

我的数据看起来这样的:

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") 
+0

不somethig像'差异( rleid(dt $ var))可以吗? (使用'data.table'中的'rleid') – Tensibai

+0

你能否澄清一下,如果一个'id'有var = c(“sleep”,“sleep”,0,0,“sleep”,“sleep” 0)'那么你是否想要在wake = c(0,0,1,0,0,0,0,0)中标记所有wakes,或者只是在wake = c(0,0, 1,0,0,0,0,0)' –

回答

4

在一个通带库data.table

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

的想法是让变种的运行长度编码(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或0时,它是diff +1 P,改变组时负(1重新开始):

​​

以及它为1,无功就是睡不着得到真正的值(可能是1,如果你包裹整个事情到as.numeric)。

输出:

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 
+0

谢谢。对不起,我对'data.table'不是很熟悉。这里的id是如何分组的? – giacomo

+0

Aww,对不起,我没有按ID分组。我在你的问题中错过了这部分。我添加了'by = id',它将通过id来计算rle:p – Tensibai

3

下应与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 

比较varvarlag作为OP做检测sleep0之间的过渡(或插曲),但将var需要的条件添加为0以仅标记来自的那些转换10至0wake1

+0

用as.integer替换as.numeric很容易理解,如wake = as.integer(var!= lag(var,default = var [1])) –

1

不是非常优雅,但这是工作。 请确保您事先按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 
2

这样做可能是受了。减去我的丑陋的方式:第+1与第i个值,看是否睡眠结束,像这样:

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 

编辑:多亏了下面的评论我更新了我的答案。

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)) 
3

假设你要标注为每个id所有awakings:

1)不包注意,如果xy是合乎逻辑的,然后当且仅当x - y > 0xTRUEyFALSE。因此,我们有一个使用无包装的情况如下:

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)动物园我们可以用使用rollapplyr沿着每个id查找序列 c(FALSE, TRUE) in 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))))