2016-06-21 8 views
11

Ich habe ein df wie so:Identifizierung von aufeinanderfolgenden Vorkommen eines Wertes

Count 
1 
0 
1 
1 
0 
0 
1 
1 
1 
0 

und ich möchte eine 1 in einer neuen Spalte zurück, wenn es zwei oder mehr aufeinanderfolgende Vorkommen von 1 in Count und ein 0 wenn da ist nicht. In der neuen Spalte würde also jede Zeile einen 1 erhalten, wenn dieses Kriterium in der Spalte Count erfüllt ist. Meine gewünschte Ausgabe wäre dann:

Count New_Value 
1  0 
0  0 
1  1 
1  1 
0  0 
0  0 
1  1 
1  1 
1  1 
0  0 

Ich denke ich brauche itertools verwenden kann, aber ich habe darüber gelesen und bin nicht gekommen, über was ich noch brauche. Ich möchte in der Lage sein, diese Methode zu verwenden, um eine beliebige Anzahl von aufeinander folgenden Vorkommen zu zählen, nicht nur 2. Zum Beispiel, manchmal muss ich 10 aufeinander folgende Vorkommen zählen, ich verwende nur 2 im Beispiel hier.

+0

Überprüfen Sie, ob 'df ['Count'] [1] == df ['Count'] [1] .shift (1)', und wenn ja, '1', sonst' 0'. Dann sollten Sie diese Werte (0 oder 1) an ein Array anhängen. Setzen Sie dann das erste Element ('array [0]') auf '0' (Standard). Dann müssen Sie herausfinden, wie Sie Ihr 'Array' in Ihren' Dataframe' einbinden, verbinden/verbinden/verketten. 100% ungetestet, aber ich denke, das kann funktionieren ... :) –

+0

Ich mag meine Frage zu sehr vereinfacht haben, was ist, wenn ich 3 aufeinander folgende Vorkommnisse möchte? Ich glaube nicht, das funktioniert dann –

Antwort

10

Sie könnten:

df['consecutive'] = df.Count.groupby((df.Count != df.Count.shift()).cumsum()).transform('size') * df.Count 

zu erhalten:

Count consecutive 
0  1   1 
1  0   0 
2  1   2 
3  1   2 
4  0   0 
5  0   0 
6  1   3 
7  1   3 
8  1   3 
9  0   0 

Von hier aus können Sie , für jede Schwelle:

threshold = 2 
df['consecutive'] = (df.consecutive > threshold).astype(int) 

zu erhalten:

Count consecutive 
0  1   0 
1  0   0 
2  1   1 
3  1   1 
4  0   0 
5  0   0 
6  1   1 
7  1   1 
8  1   1 
9  0   0 

oder, in einem einzigen Schritt:

(df.Count.groupby((df.Count != df.Count.shift()).cumsum()).transform('size') * df.Count >= threshold).astype(int) 

Im Hinblick auf die Effizienz, mit pandas Methoden stellt eine signifikante Beschleunigung, wenn die Größe des Problems wächst:

df = pd.concat([df for _ in range(1000)]) 

%timeit (df.Count.groupby((df.Count != df.Count.shift()).cumsum()).transform('size') * df.Count >= threshold).astype(int) 
1000 loops, best of 3: 1.47 ms per loop 

im Vergleich zu:

%%timeit 
l = [] 
for k, g in groupby(df.Count): 
    size = sum(1 for _ in g) 
    if k == 1 and size >= 2: 
     l = l + [1]*size 
    else: 
     l = l + [0]*size  
pd.Series(l) 

10 loops, best of 3: 76.7 ms per loop 
+0

Hier ist ein Einzeiler: 'df.assign (consequense = df.Count.groupby ((df.Count! = Df.Count.shift()). Cumsum()) ('size')) query ('konsekutiv> @threshold') 'was für alle aufeinanderfolgenden Werte funktioniert (nicht nur Einsen und Nullen) – MaxU

1

nicht sicher, ob dies optimiert ist, aber man kann es versuchen:

from itertools import groupby 
import pandas as pd 

l = [] 
for k, g in groupby(df.Count): 
    size = sum(1 for _ in g) 
    if k == 1 and size >= 2: 
     l = l + [1]*size 
    else: 
     l = l + [0]*size 

df['new_Value'] = pd.Series(l) 

df 

Count new_Value 
0 1 0 
1 0 0 
2 1 1 
3 1 1 
4 0 0 
5 0 0 
6 1 1 
7 1 1 
8 1 1 
9 0 0