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