2017-10-13 2 views
1

Eine Probe der triggers Säule in meinem Dask Datenrahmen wie folgt aussieht:Inkompatibilität von in dask und Pandas gelten Datenrahmen

0 [Total Traffic, DNS, UDP] 
1     [TCP RST] 
2    [Total Traffic] 
3     [IP Private] 
4      [ICMP] 
Name: triggers, dtype: object 

Ich wünsche eine heißen codierte Version des oben genannten Arrays erstellen (Putten a 1 gegen die DNS Spalte in Zeile 1 zum Beispiel), indem Sie Folgendes tun. pop_triggers enthält alle möglichen Werte von triggers.

for trig in pop_triggers: 
    df[trig] = df.triggers.apply(lambda x: 1 if trig in x else 0) 

jedoch die Total Traffic, DNS usw. Spalten enthalten alle den Wert 0 und nicht 1 für den entsprechenden Wert. Wenn ich es in einen Pandas-Datenrahmen kopiere und denselben Vorgang mache, erhalten sie den erwarteten Wert.

a = df[[ 'Total Traffic', 'UDP', 'NTP Amplification', 'triggers', 'ICMP']].head() 
for trig in pop_triggers: 
    a[trig] = a.triggers.apply(lambda x: 1 if trig in x else 0) 

Was fehlt mir hier? Liegt es daran, dass dask faul ist, dass es die Werte nicht wie erwartet ausfüllt?

Edit 1: Ich untersuchte einige Orte, an denen die Flagge an erster Stelle gesetzt wurde (die weit weniger entpuppte als ich erwartet hatte, und bekam einige wirklich seltsame Ergebnisse siehe unten:.

df2 = df[df['Total Traffic']==1] 
df2[['triggers']+pop_triggers].head() 

Ausgang: vielleicht

 triggers Total Traffic UDP DNS 
9380 [ICMP, IP null, IP Private, TCP null, TCP SYN,... 1 1 1 
9388 [ICMP, IP null, IP Private, TCP null, TCP SYN,... 1 1 1 
19714 [ICMP, IP null, IP Private, UDP, NTP Amplifica... 1 1 1 
21556 [IP null] 1 1 1 
21557 [IP null] 1 1 1 

möglich Fehler

Edit 2: Minimales Arbeitsbeispiel:

triggers = [['Total Traffic', 'DNS', 'UDP'],['TCP RST'],['Total Traffic'],['IP Private'],['ICMP']]*10 
df2 = dd.from_pandas(pd.DataFrame({'triggers':triggers}), npartitions=16) 
pop_triggers= ['Total Traffic', 'UDP', 'DNS', 'TCP SYN', 'TCP null', 'ICMP'] 
for trig in pop_triggers: 
    df2[trig] = df2.triggers.apply(lambda x: 1 if trig in x else 0) 
df2.head() 

Ausgang:

triggers Total Traffic UDP DNS TCP SYN TCP null ICMP 
0 [Total Traffic, DNS, UDP] 0 0 0 0 0 0 
1 [TCP RST] 0 0 0 0 0 0 
2 [Total Traffic] 0 0 0 0 0 0 
3 [IP Private] 0 0 0 0 0 0 

Hinweis: Ich bin weit mehr besorgt über die Dask Seite der Dinge und Pandas nicht

Antwort

2

In Meine Erfahrung apply in dask funktioniert viel besser mit expliziten metadata. Es gibt einige Funktionen, die dask versuchen, die metadata zu erraten, aber ich fand es langsam und nicht immer zuverlässig. Auch die Anleitung ist anzugeben meta.

Ein weiterer Punkt in meiner Erfahrung ist, dass assign besser funktioniert als . Ich bin mir nicht sicher, ob es ein Fehler, eine Einschränkung oder ein Missbrauch auf meiner Seite ist (ich habe das vor einiger Zeit recherchiert und ich glaube nicht, dass es ein Fehler ist).

EDIT: Das erste Muster nicht funktioniert, der trig Wert für vorherige Spalten in der Schleife verwendet scheint mit späteren Werten aktualisiert werden, damit bei Rechenzeit, dies für alle Spalten nur das Ergebnis des letzten Wertes gibt !

Es ist kein Fehler, sondern die Kombination von nicht sofort berechnen, während das Lambda-Ergebnis der verzögerten Berechnung auf den Verschluss, die noch nicht ausgewertet wird. Siehe this discussion für warum es nicht funktioniert.

für Sie Mein Muster wäre dann:

cols = {} 
for trig in pop_triggers: 
    meta = (trig, int) 
    cols[trig] = df.triggers.apply(lambda x: 1 if trig in x else 0, meta=meta) 
df = df.assign(**cols) 

richtige Muster:

(sorry vorher nicht getestet, da ich das gleiche Muster, außer ich don laufen Verwenden Sie den Schleifenwert in der angewendeten Funktion nicht, damit dieses Verhalten nicht auftritt.

cols = {} 

for trig in pop_triggers: 
    meta = (trig, int) 

    def fn(x, t): 
     return 1 if t in x else 0 

    cols[trig] = ddf.triggers.apply(fn, args=(trig,), meta=meta) 
ddf = ddf.assign(**cols) 
+0

Hallo Alex, ich fürchte, das hat nicht funktioniert. Überprüfe 'df.head()'. –

+0

so sehe ich, was vor sich geht, die letzte aus der Schleife berechnete Serie wird allen Spalten zugewiesen, schaut auf das Problem der Mutabilität. Das ist komisch, weil ich fast genau das gleiche Stück Code habe, das seit einigen Wochen verwendet wird ... Tatsächlich fühlt es sich so an, als ob die "Trig" im "Lambda" veränderbar bleibt und so der letzte Wert beim Rechnen verwendet wird alle Spalten. – Alex

+0

Antwort aktualisiert mit einer funktionierenden Version. Es wäre lohnenswert, mit den Entwicklern zu überprüfen, ob dies erwartetes Verhalten ist (in diesem Fall glaube ich nicht, dass Dokumente das Problem hervorheben) oder ein Fehler – Alex

Verwandte Themen