2016-10-31 5 views
1

Ich habe folgende Datenrahmen:Conditional Verfüllung von Pandas Spalten

 DATE  ID  STATUS 
0 2014-01-01 1 INPROGRESS 
1 2013-03-01 1  ENDED 
2 2015-05-01 2 INPROGRESS 
3 2012-05-01 1  STARTED 
4 2011-05-01 2  STARTED 
5 2011-03-01 3  STARTED 
6 2011-04-01 3  ENDED 
7 2011-06-01 3 INPROGRESS 
8 2011-09-01 3  STARTED 

hier der Code, es zu bauen:

>>> df1 = pd.DataFrame(columns=["DATE", "ID", "STATUS"]) 
>>> df1["DATE"] = ['2014-01-01', '2013-03-01', '2015-05-01', '2012-05-01', '2011-05-01', '2011-03-01', '2011-04-01', '2011-06-01', '2011-09-01'] 
>>> df1["ID"] = [1,1,2,1,2,3,3,3,3] 
>>> df1["STATUS"] = ['INPROGRESS', 'ENDED', 'INPROGRESS', 'STARTED', 'STARTED', 'STARTED','ENDED', 'INPROGRESS', 'STARTED'] 

für jede ID-Gruppe die Statusspalte eine Aufgabe darstellt, die sein kann:

STARTED, INPROGRESS oder ENDED

in dieser genauen Zeitfolge (STARTED sollte Nr t kam nach ENDED etc ..).

Durch die Gruppierung von ID und die Sortierung nach Datum, das ich für ID erhalten 3:

df1.sort_values('DATE')[df1['ID']==3] 

    DATE  ID  STATUS 
5 2011-03-01 3  STARTED 
6 2011-04-01 3  ENDED 
7 2011-06-01 3 INPROGRESS 
8 2011-09-01 3  STARTED 

Nein ich brauchen würde, um den Status Spalte auf „FIX“ die Reihenfolge oben auf der Grundlage der letzten Status definiert zu folgen. Für die ID 3 den letzten Zustand gestartet, so sollte alles auf den gestarteten Status wie folgt zu verfüllen:

 DATE  ID  STATUS 
5 2011-03-01 3  STARTED 
6 2011-04-01 3  STARTED 
7 2011-06-01 3  STARTED 
8 2011-09-01 3  STARTED 

für ID 1:

df1.sort_values('DATE')[df1['ID']==1] 
    DATE ID  STATUS 
3 2012-05-01 1  STARTED 
1 2013-03-01 1  ENDED 
0 2014-01-01 1 INPROGRESS 

ich würde am Ende des letzten zwei Status INPROGRESS mit und Lassen Sie die erste als STARTED wie:

df1.sort_values('DATE')[df1['ID']==1] 
    DATE ID  STATUS 
3 2012-05-01 1  STARTED 
1 2013-03-01 1 INPROGRESS 
0 2014-01-01 1 INPROGRESS 

ID 2 hat die richtige Reihenfolge.

Irgendeine Idee, wie kann ich das mit Pandas tun? Ich versuche durch Gruppierung nach ID und ich denke über Backfill nach dem letzten Status nach, aber ich weiß nicht, wie ich im richtigen Moment die Verfüllung stoppen könnte.

danke!

Antwort

2

Ein klassischer Weg ist es zu vergessen, dass Ihre Status sind Beschriftungen: stattdessen sehen sie als streng steigende Zahlen, wie gestartet 1, in Bearbeitung 2 und endete 3. Mit einer solchen Spalte können Sie jetzt die Monotonie dieser Zahlen pro Gruppe prüfen, dann auffüllen, bis Sie eine Unterbrechung der Monotonie sehen.

Bereiten Sie Ihren Datenrahmen:

keymapping = {'STARTED':0, 'INPROGRESS':1, 'ENDED':2} 
df['STATUS_ID'] = df.STATUS.map(keymapping) 
df.set_index(['ID', 'DATE'], inplace=True) 
df.sort_index(inplace=True) 

Nun Gruppe von ID und verwenden transform den letzten Wert jeder Gruppe verteilt über den gesamten Index zu bekommen, so dass Sie es zu Ihrem Datenrahmen als neue Spalte zuweisen :

df['STATUS_LAST'] = df.groupby(level=0, as_index=False).STATUS_ID.transform('last') 

df 
Out[63]: 
        STATUS STATUS_ID STATUS_LAST 
ID DATE           
1 2012-05-01  STARTED   0   1 
    2013-03-01  ENDED   2   1 
    2014-01-01 INPROGRESS   1   1 
2 2011-05-01  STARTED   0   1 
    2015-05-01 INPROGRESS   1   1 
3 2011-03-01  STARTED   0   0 
    2011-04-01  ENDED   2   0 
    2011-06-01 INPROGRESS   1   0 
    2011-09-01  STARTED   0   0 

die Verfüllung Schließlich gelten die zunehmende Monotonie des STATUS_ID gegen letzten Verwendung, dh jeder Wert von STATUS_ID gültig ist, wenn, wenn kleiner oder gleich STATUS_LAST ist:

df.STATUS_ID = df.STATUS_ID.where(df.STATUS_ID <= df.STATUS_LAST, df.STATUS_LAST) 
df.STATUS_ID 
Out[65]: 
ID DATE  
1 2012-05-01 0 
    2013-03-01 1 
    2014-01-01 1 
2 2011-05-01 0 
    2015-05-01 1 
3 2011-03-01 0 
    2011-04-01 0 
    2011-06-01 0 
    2011-09-01 0 

Reverse-Karte, um diese auf die Etiketten und weisen es STATUS:

df.STATUS_ID.map({v:k for k,v in keymapping.items()}) 
Out[66]: 
ID DATE  
1 2012-05-01  STARTED 
    2013-03-01 INPROGRESS 
    2014-01-01 INPROGRESS 
2 2011-05-01  STARTED 
    2015-05-01 INPROGRESS 
3 2011-03-01  STARTED 
    2011-04-01  STARTED 
    2011-06-01  STARTED 
    2011-09-01  STARTED 
Name: STATUS_ID, dtype: object