2016-09-02 2 views
1

Ich arbeite mit einem DataFrame, bei dem jeder Zeilenbeobachtung ein ordinales Datetime-Objekt zugeordnet ist. Ich habe eine Funktion geschrieben, dass ich schaut durch meine Datenrahmen glauben und identifiziert nacheinander auftretenden Tage und die Länge des Laufes dieser nacheinander auftretenden Tage mit dem folgenden Code:Identifizieren konsekutiver Sequenzen von Daten und Zählen ihrer Längen

def consecutiveCount(df): 
    df= df.copy() 
    cond1 = df['DATE_INT'].shift(-1) - df['DATE_INT'] == 1 
    cond2 = df['DATE_INT'].shift(1) - df['DATE_INT'] == -1 

    cond3 = df['DATE_INT'].shift(-2) - df['DATE_INT'] == 2    
    cond4 = df['DATE_INT'].shift(2) - df['DATE_INT'] == -2 

Jetzt fahre ich fort, diese Bedingungen in der gleichen Art und Weise zu machen bis zu dem Punkt:

cond55 = df['DATE_INT'].shift(-28) - df['DATE_INT'] == 28    
    cond56 = df['DATE_INT'].shift(28) - df['DATE_INT'] == -28 

    cond57 = df['DATE_INT'].shift(-29) - df['DATE_INT'] == 29    
    cond58 = df['DATE_INT'].shift(29) - df['DATE_INT'] == -29 

I dann um die Länge des 'Run' von Tagen in einer Spaltenvariable schreiben mit dem folgenden Code:

df.loc[cond1 | cond2, 'CONSECUTIVE_COUNT'] = 2 
    df.loc[cond3 | cond4, 'CONSECUTIVE_COUNT'] = 3 

wieder ich weiter, bis ich ‚läuft‘ der Tage der Länge 30.

df.loc[cond55 | cond56, 'CONSECUTIVE_COUNT'] = 29 
    df.loc[cond57 | cond58, 'CONSECUTIVE_COUNT'] = 30 

Schließlich wende ich die Funktion auf bestimmte Gruppen von meiner Datenrahmen wie folgt erreichen:

df1 = df.groupby(['COUNTY_GEOID_YEAR','TEMPBIN']).apply(consecutiveCount) 

Ich bin sicher, dass es viel sind effizientere Möglichkeiten, diesen Code zu schreiben. Ich habe den Flaschenhals in meinem Skript identifiziert, wenn ich die Funktion durch Drucken verschiedener Strings in meinem Skript anwende.

Jede Hilfe beim Schreiben der Funktion auf eine effizientere Art und Weise oder wie man die Anwendung beschleunigt, wäre großartig! Bitte lassen Sie mich wissen, wenn ich weitere Informationen zur Verfügung stellen kann.

EDIT: Wie @DSM wies darauf hin, dass mein Code nicht genau die Länge der aufeinanderfolgenden Läufe von Tagen richtig zählt. Seine Lösung hat so genau für mich gemacht!

+0

Ihr aktueller Code scheint so zu sein, als würde es bedeuten, dass eine DATE_INT-Spalte von [1,2,3,4] (für die gleiche COUNTY_GEOID_YEAR und TEMPBIN) aufeinanderfolgende Zählungen von [4,3,3,4] hätte. Ich bin mir nicht sicher, ob ich die Logik dort verstehe. – DSM

+0

oh - du hast recht, danke, dass du das gezeigt hast. Das ist nicht was ich will - ich werde versuchen, Ihre Lösung unten zu implementieren. – Justin

Antwort

1

IIUC, können Sie das Shift-compare-cumsum-Muster nach dem Anwenden Ihrer groupby verwenden, und dann eine Transformation durchführen.

Unter der Annahme, dass Ihre Daten in etwa so aussieht (vereinfacht ein wenig)

df = pd.DataFrame({"GEOID_YEAR": [2000]*10 + [2001]*4, "TEMPBIN": [1]*14, 
        "DATE_INT": [1,2,3,4,6,7,9,10,11,14] + list(range(14,18)), 
        "OTHER_COL": [2]*14}) 

oder

DATE_INT GEOID_YEAR OTHER_COL TEMPBIN 
0   1  2000   2  1 
1   2  2000   2  1 
2   3  2000   2  1 
3   4  2000   2  1 
4   6  2000   2  1 
5   7  2000   2  1 
6   9  2000   2  1 
7   10  2000   2  1 
8   11  2000   2  1 
9   14  2000   2  1 
10  14  2001   2  1 
11  15  2001   2  1 
12  16  2001   2  1 
13  17  2001   2  1 

dann

df["cons_id"] = df.groupby(["GEOID_YEAR", "TEMPBIN"])["DATE_INT"].apply(
    lambda x: (x != x.shift() + 1).cumsum()) 
df["cons_count"] = (df.groupby(["GEOID_YEAR", "TEMPBIN", "cons_id"]) 
        ["cons_id"].transform("count")) 

gibt uns

In [78]: df 
Out[78]: 
    DATE_INT GEOID_YEAR OTHER_COL TEMPBIN cons_id cons_count 
0   1  2000   2  1  1   4 
1   2  2000   2  1  1   4 
2   3  2000   2  1  1   4 
3   4  2000   2  1  1   4 
4   6  2000   2  1  2   2 
5   7  2000   2  1  2   2 
6   9  2000   2  1  3   3 
7   10  2000   2  1  3   3 
8   11  2000   2  1  3   3 
9   14  2000   2  1  4   1 
10  14  2001   2  1  1   4 
11  15  2001   2  1  1   4 
12  16  2001   2  1  1   4 
13  17  2001   2  1  1   4 
+0

Die Anwendung der Lösung hat mir einen ValueError verursacht, der von der zweiten Gruppe beim Erstellen von 'cons_count' verursacht wurde. Ändern des Codes zu df.groupby (['COUNTY_GEOID_YEAR', 'TEMPBIN']) ['cons_id']. Transform ('count') hat den Trick gemacht. Ich überprüfe jetzt nur, dass dies zu dem führt, was ich wollte. Danke für die Hilfe. – Justin

+0

@Justin: Ach, tut mir leid, ja - ich nahm an, dass es keine anderen Spalten gab. Ich werde modifizieren. – DSM

Verwandte Themen