2017-05-23 6 views
0

ich einen Datenrahmen, die Mitarbeiter Anwesenheits Geschichte und es sieht aus wie die folgenden Datensätze: von IDVerwenden Python Pandas oder R, organisieren Kalenderdaten

ID Sunday Monday Tuesday Wednesday Thursday Friday Saturday 
1585 NA  NA  NA  NA  NA  NA  NA 
1585 NA  S  S  S   S  H  NA 
1585 NA  H  S  S  NA  NA  NA 
1585 NA  S  S  S  NA  NA  NA 
1597 NA  S  S  NA   S  NA  NA 
1597 NA  NA  NA  NA  NA  H  NA 
1597 NA  H  S  S  NA  NA  NA 
1597 NA  NA  NA  NA  NA  NA  NA 

In dem obigen Beispiel gibt es zwei Personen eindeutig identifiziert Die folgenden 7 Spalten sind Samstag bis Sonntag, die am 1. April 2017 beginnen. Es gibt drei Anwesenheitsverhalten: S bedeutet kranker Urlaub, H steht für Feiertage und NA bedeutet, dass diese Person an diesem Tag arbeitet.

Das Interesse besteht darin, die Krankenstandabwesenheitsakten neu zu organisieren. Beispiel: Die Person 1585 beginnt am Montag, dem 10. April 2017, krankheitsbedingt und endet am Mittwoch, den 19. April 2017 und dauert 10 Tage. Beachten Sie, dass es während der 10 Tage zwei Feiertage gibt, die jedoch zu diesem Krankheitsurlaub gehören würden. Dann beginnt diese Person am Montag, den 24. April 2017, einen zweiten Krankenstand und endet am Mittwoch, dem 26. April.

Wir haben auch eine Aufzeichnung über die zweite Person mit ID 1597, beginnt wieder am 1. April 2017 (so für jede Person, die Anfangs- und Enddaten der Datensätze sind die gleichen). Diese Person hat drei Abwesenheitszauber: der erste beginnt am Montag, dem 3. April 2017 und endet am nächsten Tag, dem 4. April. Der zweite Zauber dauert nur einen Tag und beginnt und endet am 6. April. Der letzte Spruch beginnt am 18. April und endet am 19. April.

Die gewünschte Ausgabe wie folgt sein würde:

ID  Begin_date End_date Duration 
1585 2017-04-10 2017-04-19 10 
1585 2017-04-24 2017-04-26 3 
1597 2017-04-03 2017-04-04 2 
1597 2017-04-06 2017-04-06 1 
1597 2017-04-18 2017-04-19 2 

Die Schwierigkeit, die ich konfrontiert ist, wie die aufeinander folgenden Krankendaten zu erkennen, und oben auf, dass während eines einzigen Kranken Zauber, ist es möglich, haben unterschiedliche Arten von Anwesenheitstypen (Ferien), aber Ferien werden immer noch als zu diesem einzelnen Krankenurlaubszauber gehörend betrachtet.

+1

Ihre Eingabe nur Tage der Woche hat aber den gewünschten Ausgang hat bestimmte Daten. –

+0

Ich würde in Betracht ziehen, Ihre Quelldaten so zu ändern, dass sie "Date, Status, employeeID" melden.Auf diese Weise können Sie einen Zeitreihen-Datenrahmen erstellen und anschließend eine kumulative Summe aufeinanderfolgender Tage erstellen, um die gewünschte Ausgabe zu erhalten. – Henry

+0

Ja, der Datensatz ist auf einer täglichen Basis, für jeden einzelnen beginnen und enden die Datensätze immer am selben Datum. In dieser Stichprobe haben alle Personen am 1. April 2017 Aufzeichnungen und enden am 28. April. So können wir implizit die spezifischen Daten erkennen. – skyindeer

Antwort

1

Basierend auf der Idee von @Cholts, ich einen R-Code schreiben, um die gewünschte Ausgabe

Erzeugung
#clean the workspace 
rm(list=ls(all=TRUE)) 
require(tidyr) 
library(dplyr) 
library(lubridate) 
library(stringr) 

ID = c(rep(1585,4),rep(1597,4)) 
Sun = c(rep("D",8)) 
Sat = c(rep("D",8)) 
Mon = c("Y","S","H","S","S","Y","H","Y") 
Tue = c("Y","S","S","S","S","Y","S","Y") 
Wed = c("Y","S","S","S","Y","Y","S","Y") 
Thur = c("Y","S","Y","Y","S","Y","Y","Y") 
Fri = c("Y","H","Y","Y","Y","H","Y","Y") 
id_u = unique(ID) 
df = data.frame(Sun,Mon,Tue,Wed,Thur,Fri,Sat) 

new_df = df %>% unite(new,Sun,Mon,Tue,Wed,Thur,Fri,Sat,remove=FALSE,sep="") 
vstr = new_df$new 


#=========================================================== 
idd = c() 
begin_date = c() 
end_date = c() 
duration = c() 

n = 2 
start_date = ymd('2017-04-02') 

for(i in 1:n){ 
    ps = (i-1)*4 +1 
    pe = (i-1)*4 + 4 
    indstr = paste(vstr[ps:pe],collapse = "") 
    loca = str_locate_all(indstr,"S[SHD]*S|S") 

    rn = length(loca[[1]][,1]) 
    for (j in 1:rn){ 
    idd = append(idd,id_u[i]) 
    begin_date = append(begin_date,ymd(start_date+loca[[1]][j,1]-1)) 
    end_date = append(end_date,ymd(start_date+loca[[1]][j,2]-1)) 
    duration = append(duration,loca[[1]][j,2]-loca[[1]][j,1]+1) 
    } 

} 

final_df = data.frame(idd,begin_date,end_date,duration) 

Der Ausgang ist

> final_df  
    idd begin_date end_date duration 
1 1585 2017-04-10 2017-04-19  10 
2 1585 2017-04-24 2017-04-26  3 
3 1597 2017-04-03 2017-04-04  2 
4 1597 2017-04-06 2017-04-06  1 
5 1597 2017-04-18 2017-04-19  2 
1

Sie erwähnen, dass eines Ihrer größten Probleme darin besteht, krankheitsbedingte Spells zu erkennen, da sie Feiertage und Wochenenden einschließen können. Es kommt mir vor, dass ein Krankheitsurlaub als Regex dargestellt werden könnte. Hier ist eine mögliche Lösung, die davon profitiert:

Zuerst ersetzen Sie alle NAs am Wochenende mit "D" und alle NAs an Wochentagen mit 'Y' (oder andere 2 Zeichen). In Ihrem Beispiel werden normale Wochenenden anders behandelt als normale Wochentage, da Abwesenheitszauber normale Wochenenden, aber keine normalen Wochentage enthalten können. Daher sollten sie einen anderen Wert haben.

Dann für jede ID, flattern Sie die Daten, und verketten Sie sie in eine Zeichenfolge. Abwesenheitszauber können durch Regex als "(S[SHD]*S)|S" identifiziert werden. Erstellen Sie für jede gefundene Regex-Zeichenfolge eine Zeile in Ihrer neuen Tabelle, wobei das Anfangsdatum, das Enddatum und die Dauer des Abwesenheitszaubers auf der Startposition, der Endposition und der Länge der gefundenen Zeichenfolge basieren.

Damit diese Lösung funktioniert, müssen wir davon ausgehen, dass jede ID die gleiche Anzahl von Zeilen hat, die denselben Datumsangaben entsprechen, sodass wir Startpositionen der Zeichenfolgen den Daten richtig zuordnen können.

+0

Ich denke, ich finde die möglichen Befehle in R, sie sind 'stringr :: str_locate_all()' und 'striadr :: str_extract_all()'. Danke fürs Helfen !!! – skyindeer

Verwandte Themen