2017-11-13 2 views
2

Ich muss Beobachtungen, die eine Bedingung, ein binäres Flag, an bestimmten Daten erfüllen, in eine Tabelle mit Beobachtungen mit dem Datumsbereich umwandeln, in dem sie das Flag erfüllen.Zeilen von sequentiellen Datumsangaben in Spalte mit Datumsbereich umwandeln

Beispieldaten sehen wie folgt aus:

id <- c(1001, 1001, 1001, 1002, 1002, 1002, 1003, 1003, 1003) 
date <- c("2016-06-20", "2016-06-21", "2016-06-22", "2016-06-20", 
      "2016-06-21", "2016-06-22", "2016-06-20", "2016-06-21", 
      "2016-06-22") 
flag <- c(1, 0, 0, 1, 1, 0, 1, 0, 1) 
mydata <- data.frame(id, date, flag) 

    id  date flag 
1001 2016-06-20 1 
1001 2016-06-21 0 
1001 2016-06-22 0 
1002 2016-06-20 1 
1002 2016-06-21 1 
1002 2016-06-22 0 
1003 2016-06-20 1 
1003 2016-06-21 0 
1003 2016-06-22 1 

ich dies als ein zweistufiger Prozess denke.

Schritt 1: Bestimmen Sie, ob das Flag an aufeinanderfolgenden Tagen auftritt.

Dies ist ähnlich zu dieser Frage - R, find, dates, consecutive - aber mit einer Bedingung, wenn flag > 0. Ich versuche, die Lösung anzuwenden, obwohl es nicht ganz so funktioniert.

mydata$flag_consecutive <- mydata$flag > 0 & c(NA, diff(as.Date(mydata$date)) == 1) 


    id  date flag flag_consecutive 
1001 2016-06-20 1    NA 
1001 2016-06-21 0   FALSE 
1001 2016-06-22 0   FALSE 
1002 2016-06-20 1   FALSE 
1002 2016-06-21 1    TRUE 
1002 2016-06-22 0   FALSE 
1003 2016-06-20 1   FALSE 
1003 2016-06-21 0   FALSE 
1003 2016-06-22 1    TRUE 

Schritt 2: erstellen Datumsbereich Spalten

Ich bin mir nicht sicher, wie dieser Teil in R. mit Vektorisierung zu nähern Wenn das Flag nur an einem Tag stattfindet, das Start- und Enddatum sind gleich. Wenn das Flag an aufeinanderfolgenden Tagen auftritt, möchte ich den ersten Tag in der Folge als date_start und den letzten Tag als date_end setzen. Wenn kein Flag auftritt, löschen Sie das aus dem Dataset.

Was Ich mag würde erzeugen, ist die auf diese Weise formatierten Daten:

id flag date_start  date_end 
1001 1 2016-06-20 2016-06-20 
1002 1 2016-06-20 2016-06-21 
1003 1 2016-06-20 2016-06-20 
1003 1 2016-06-22 2016-06-22 

Wenn Sie Hinweise zu Schritt 1 oder Schritt 2 zur Verfügung stellen kann, bin ich sehr dankbar. Ich denke im Kreis und bin mir nicht sicher, ob Schritt 1 überhaupt nötig ist.

Antwort

2

Eine mögliche Lösung, um die data.table -package mit:

library(data.table) 
setDT(mydata)[, rl := rleid(flag) 
       ][flag == 1 
       , .(date_start = first(date), date_end = last(date)) 
       , by = .(id, rl, flag) 
       ][, rl := NULL][] 

die gibt:

 id flag date_start date_end 
1: 1001 1 2016-06-20 2016-06-20 
2: 1002 1 2016-06-20 2016-06-21 
3: 1003 1 2016-06-20 2016-06-20 
4: 1003 1 2016-06-22 2016-06-22 

Was das bedeutet:

  • rl := rleid(flag) schafft eine Gruppierung v . Ariable rl für jeweils aufeinanderfolgende Reihen von flag s
  • Filter mit flag == 1
  • Gruppe mit `by = (id, rl, flag)
  • für jede Gruppe die erste und die letzte Beobachtung Wählen mit .(date_start = first(date), date_end = last(date)); Wenn nur ein Wert vorhanden ist, wählen first und last diesen Wert aus.

Ein äquivalenter Ansatz mit dplyr:

library(dplyr) 
mydata %>% 
    mutate(rl = cumsum(flag != lag(flag, default = 1))) %>% 
    filter(flag == 1) %>% 
    group_by(id, flag, rl) %>% 
    summarise(date_start = first(date), 
      date_end = last(date)) %>% 
    select(-rl) 
Verwandte Themen