2016-11-28 2 views
2

Ich versuche einen Vektor zu erzeugen, der das Ende einer Sequenz anzeigt.Finde die erste Sequenzepisode

sieht Meine Daten dieses:

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 

Was ich will, ist dies (Ausgabe wollte)

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 

Ich war wie

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 

jedoch an etwas gedacht, es erkennt nicht die erste Episode nur

Daten

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

wie nicht somethig Hat 'diff (rleid (dt $ var)) 'ok? (mit 'rleid' aus' data.table') – Tensibai

+0

Kannst du klarstellen, dass, wenn ein 'id'' var = c hat ("schlafen", "schlafen", 0, 0, "schlafen", "schlafen", 0, 0) 'wollen Sie dann alle Wakings wie in' wake = c (0, 0, 1, 0, 0, 0, 1, 0) 'oder nur die erste wie in' wake = c (0, 0, 1, 0, 0, 0, 0, 0) ' –

Antwort

4

In einem Durchgang mit Bibliothek data.table:

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

Die Idee ist es, die Lauflängencodierung von var (rleid) zu erhalten:

> 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 

Und es ist diff +1, wenn aus dem Schlaf auf 0, oder 0 zu schlafen p, negativ, wenn die Gruppe zu ändern (Start wieder auf 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 

Und wo es 1 und var schlafen ist kein echten Wert erhalten (könnte 1 sein, wenn man das Ganze in as.numeric wickelt).

Ausgang:

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

danke. Tut mir leid, ich bin nicht sehr vertraut mit 'data.table'. Wie ist die ID hier gruppiert? – giacomo

+0

Aww, sorry, ich habe nicht nach ID gruppiert. Ich habe diesen Teil in deiner Frage vermisst. Ich fügte die 'by = id 'hinzu, die die rle durch die ID berechnen würde: p – Tensibai

3

Die folgende Beschreibung ist mit dplyr arbeiten:

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 

Vergleichen var mit lag von var als die OP den Übergang (oder Folge) zwischen sleep und 0 zu erkennen, hat aber Fügen Sie die Bedingung hinzu, dass var0 sein muss, um nur diese Übergänge vonzu markieren 10 bis 0 für wake zu 1 sein.

+0

Es ist leicht zu verstehen, as.numeric durch as.integer zu ersetzen, als wake = as.integer (var! = Lag (var, default = var [1])) –

1

Nicht sehr elegant, aber das macht den Job. Stellen Sie sicher, dass Sie vorher die dt ID und Zeit sortieren.

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

Eine hässliche Art und Weise, dies zu tun durch subtrahieren der ich sein könnte: mit dem i-ten +1: ten Wert zu sehen, ob der Schlaf beendet, wie folgt aus:

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 

dann können Sie einfach folgenden Code schreiben wake zu erhalten:

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 

EDIT: dank den Kommentaren unten ich meine Antwort aktualisiert.

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

Unter der Annahme, dass Sie alle awakings für jede id markieren möchten:

1) keine Pakete Beachten Sie, dass, wenn x und y logisch sind dann x - y > 0 iff x ist TRUE und yFALSE ist. So haben wir die folgende, die keine Pakete verwendet:

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

2) dplyr Alternativ kann es in Bezug auf dplyr wie folgt geschrieben werden:

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

3) Zoo Wir verwenden können rollapplyr entlang jeder id auf der Suche nach der Sequenz c(FALSE, TRUE) in var==0. Das Hinzufügen von 0 stellt sicher, dass das Ergebnis numerisch ist.

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

Hinweis: Wenn Sie wollten für jeden id nur das erste Erwachen markieren und wenn out sind das Ergebnis einer der oben genannten dann:

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