2016-10-13 8 views
2

Ich habe einen Datenrahmen mit dieser Struktur:Pandas groupby countIf mit dynamischen Spalten

time,10.0.0.103,10.0.0.24 
2016-10-12 13:40:00,157,172 
2016-10-12 14:00:00,0,203 
2016-10-12 14:20:00,0,0 
2016-10-12 14:40:00,0,200 
2016-10-12 15:00:00,185,208 

Es wird ausführlich auf die Anzahl der Ereignisse pro IP-Adresse für einen Zeitraum von 20 Minuten gegeben. Ich brauche einen Datenrahmen, wie viele 20-Minuten-Perioden pro Bergmann 0 Ereignisse hatten, aus denen ich die IP-Uptime als Prozent ableiten muss. Die Anzahl der IP-Adressen ist dynamisch. Gewünschte Ausgabe:

IP,noEvents,uptime 
10.0.0.103,3,40 
10.0.0.24,1,80 

Ich habe versucht, mit groupby, agg und Lambda ohne Erfolg. Was ist der beste Weg, um einen 'Countif' durch dynamische Spalten zu machen?

+0

Wenn Bergmann IP '10.0.0.103' hat 3 Perioden (von 5) ohne Unfälle, sollte seine Betriebszeit nicht 60% sein? – unutbu

+0

Nun, ja. Mein Fehler. – user6949779

Antwort

3

Sie können sum und mean der booleschen Maske von Bedingung df == 0 verwenden. Letzte concat beide Series:

df.set_index('time', inplace=True) 
mask = (df == 0) 
print (mask) 
        10.0.0.103 10.0.0.24 
time          
2016-10-12 13:40:00  False  False 
2016-10-12 14:00:00  True  False 
2016-10-12 14:20:00  True  True 
2016-10-12 14:40:00  True  False 
2016-10-12 15:00:00  False  False 

noEvents = mask.sum() 
print (noEvents) 
10.0.0.103 3 
10.0.0.24  1 
dtype: int64 

uptime = 100 * mask.mean() 
print (uptime) 
10.0.0.103 60.0 
10.0.0.24  20.0 
dtype: float64 

print (pd.concat([noEvents, uptime], axis=1, keys=('noEvents','uptime')) 
     .reset_index() 
     .rename(columns={'index':'IP'})) 

      IP noEvents uptime 
0 10.0.0.103   3 60.0 
1 10.0.0.24   1 20.0 
2

Transponieren der DF:

df = df.T 

Da Sie nach dem Vorbild der mit groupby versucht, könnten Sie weiter vorgehen value_counts mit der Anzahl der Nullen in jeder Gruppe erhalten nach dem Stapeln ihm ein series Objekt zu erzeugen, und es später in die DF entstapeln zurück, wie gezeigt:

grp = df.stack().to_frame('val').groupby(level=0)['val'] 
df['noEvents'] = grp.value_counts().unstack()[0] 
Später

, teilen Sie die Werte mit der Größe dieser Gruppe Verteilung ist es Prozentsatz zu erhalten:

df['upTime'] = (100*df['noEvents']/grp.size()) 

für ästhetische Zwecke:

df = df[['noEvents', 'upTime']].astype(int) 
df.index.name = 'IP' 
df.columns.name = None 
df 

Image