2016-07-29 5 views
4

Ich habe einen Datensatz von Textfeld Interaktionen über mehrere Dutzend Benutzer meiner Anwendung über den Zeitraum von mehreren Monaten. Ich versuche, die durchschnittliche Zeit zwischen Tastenanschlägen in Pandas zu berechnen. Die Daten in etwa so aussehen:Berechnung der Zeit zwischen Textfeldinteraktionen

timestamp    before_text  after_text 
1453481138188     NULL    a 
1453481138600      a    ab 
1453481138900     ab    abc 
1453481139400     abc   abcd 
1453484000000 Enter some numbers    1 
1453484000100      1    12 
1453484000600     12    123 

timestamp enthalten die Unix-Zeit, dass der Benutzer die Taste gedrückt wird, before_text ist das, was das Textfeld vor dem Benutzer enthielt die Taste drücken, und after_text ist, was das Feld sah aus wie nach der Tastenanschlag.

Was ist der beste Weg, dies zu tun? Ich weiß, das ist nicht so einfach wie etwas zu tun:

weil dies eine sehr große Zeitdifferenz an der Grenze zwischen zwei Wechselwirkungen berechnen wird. Es scheint, als wäre der beste Weg dies zu tun, eine Funktion jeder Zeile an df.groupby zu übergeben, so dass ich das obige Snippet auf jede Zeile anwenden kann. Wenn ich diese magic_function hatte, konnte ich so etwas wie:

df.groupby(magic_function).apply(lambda x: x["timestamp"] - x["timestamp"].shift()).mean() 

Was ein guter Weg ist magic_function zu implementieren, oder bin ich über das alles falsch gedacht?

Antwort

2

Ich würde es tun, indem Sie den Text Unterschied zwischen "vor" und "nach" berechnen. Wenn die Differenz größer als ein Schwellenwert ist, ist dies eine neue Sitzung.

Es erfordert from Levenshtein import distance as ld. Ich installierte es über pip wie so:

pip install python-levenshtein 

Dann:

from Levenshtein import distance as ld 
import pandas as pd 

# taking just these two columns and transposing and back filling. 
# I back fill for one reason, to fill that pesky NA with after text. 
before_after = df[['before_text', 'after_text']].T.bfill() 

distances = before_after.apply(lambda x: ld(*x)) 

# threshold should be how much distance constitutes an obvious break in sessions. 
threshold = 2 
magic_function = (distances > 2).cumsum() 

df.groupby(magic_function) \ 
    .apply(lambda x: x["timestamp"] - x["timestamp"].shift()) \ 
    .mean() 

362.4 
+0

+1 Als beste Antwort ausgewählt, weil es sich um eine für Schleife vermeidet die Verwendung und Nutzung von vektorisiert Operationen macht Pandas. – PastyWhiteMike

+1

FYI, @PastyWhiteMike: '.apply()' ist eine 'for' Schleife, nicht vektorisiert. – Kartik

+0

Ich denke, Sie können hier vektorisierten Ansatz verwenden: 'df.groupby (magic_function) .timestamp.diff(). Mean()' – MaxU

0

Ihr Problem besteht im Wesentlichen darin, zu erkennen, wann eine bestimmte Interaktion stoppt und wann eine andere beginnt. Vielleicht berechnen Sie den Unterschied zwischen timestamp s, und wenn größer als ein Schwellenwert, setzen Sie ein Flag, auf dem Sie gruppieren können.

thresh = 1e5 
ts = (df['timestamp'] - df['timestamp'].shift()) > thresh 
grp = [0] 
for i in range(len(ts)): 
    if ts.iloc[i]: 
     grp.append(grp[-1] + 1) 
    else: 
     grp.append(grp[-1]) 
grp.append(grp[-1]) 
df['grouper'] = grp 

Jetzt können Sie einfach Gruppe wie folgt: grouped = df.groupby('grouper'), dann subtrahieren die timestamp s innerhalb der Gruppe, und berechnen die durchschnittliche Differenz.

Ich versuche einen Weg zu finden, die Schleife zu vermeiden, aber bis dann versuchen Sie dies und lassen Sie mich wissen, wie es geht.