2017-10-30 2 views
1

Ich habe DatenrahmenPandas: diff zwischen den Spalten

site1 time1 site2 time2 site3 time3 site4 time4 site5 time5 ... time6 site7 time7 site8 time8 site9 time9 site10 time10 target 
session_id                     

21669 56 2013-01-12 08:05:57 55.0 2013-01-12 08:05:57 NaN NaT NaN NaT NaN NaT ... NaT NaN NaT NaN NaT NaN NaT NaN NaT 0 
54843 56 2013-01-12 08:37:23 55.0 2013-01-12 08:37:23 56.0 2013-01-12 09:07:07 55.0 2013-01-12 09:07:09 NaN NaT ... NaT NaN NaT NaN NaT NaN NaT NaN NaT 0 
77292 946 2013-01-12 08:50:13 946.0 2013-01-12 08:50:14 951.0 2013-01-12 08:50:15 946.0 2013-01-12 08:50:15 946.0 2013-01-12 08:50:16 ... 2013-01-12 08:50:16 948.0 2013-01-12 08:50:16 784.0 2013-01-12 08:50:16 949.0 2013-01-12 08:50:17 946.0 2013-01-12 08:50:17 0 

ich zwischen dem letzten nicht NaN Zeit und zum ersten Mal diff zählen muß.

Wunsch Ausgang (Umwandlung in zweiten)

session_id diff 
21669   0 
54843  2013-01-12 09:07:09 - 2013-01-12 08:37:23 55.0 
77292  4 

ich es für jedes Paar zu können und neben fusionieren dass

df['diff1'] = df['time1'] - df['time2'] 
... 

Aber ist eine Möglichkeit, es schneller zu machen?

+1

Sie könnten die Beantwortung Ihrer Frage erleichtern, wenn Sie eine bequeme Möglichkeit zur Erstellung der Beispieldaten haben. – piRSquared

Antwort

1

Verwenden .ffill() auf dem Datenrahmen nur mit den time Spalten:

df['diff1'] = df.filter(like='time').ffill(axis = 1).time10 - df.time1 
2
  • ließ ich target
  • ich teilen Sie Ihre Spalten in eine pd.MultiIndex
  • stellte sicher, dass die Zeitstempel tatsächlich Zeitstempel waren (keine Notwendigkeit, tun Sie dies an Ihrem Ende, wenn Sie nicht tun)
  • groupby'session_id' t henne verwendet 'first' und 'last', um die ersten und letzten Nicht-Null-Werte zu erhalten.
  • pipe bequem passieren zu einer Funktion zur Folge hat, die für mich Verwenden

d = df.drop('target', 1) 
a = d.columns.str.extract('([a-z]+)(\d+)', expand=True).values.T 
mux = pd.MultiIndex.from_arrays([a[0], a[1].astype(int)]) 
d.columns = mux 

for (c0, c1), col in d.iteritems(): 
    if c0 == 'time': 
     d[(c0, c1)] = pd.to_datetime(col, errors='coerce') 

f = lambda d: d['last'].sub(d['first']).dt.total_seconds() 
d.time.stack().groupby('session_id').agg(['last', 'first']).pipe(f) 

session_id 
21669  0.0 
54843 1786.0 
77292  4.0 
dtype: float64 
2

subtrahiert:


a = df.filter(like='time').notnull().iloc[:, ::-1].idxmax(1) 
print (a) 
0 time2 
1 time4 
2 time5 
dtype: object 

df['diff']= pd.Series(df.lookup(df.index,a),index=df.index) 
       .sub(df['time1']) 
       .dt.total_seconds() 
print (df['diff']) 
0  0.0 
1 1786.0 
2  4.0 
Name: diff, dtype: float64 

numpy alternative:

A = df.filter(like='time') 
b = len(A.columns) - A.notnull().values[:, ::-1].argmax(1) - 1 

df['diff'] = pd.Series(A.values[np.arange(len(A)),b]).sub(df['time1']).dt.total_seconds() 
print (df['diff']) 
0  0.0 
1 1786.0 
2  4.0 
Name: diff, dtype: float64 

Allgemeinere Ken Wei Lösung - wählt erste und letzte Spalte von iloc:

df1 = df.filter(like='time') 
df['diff']= df1.ffill(1).iloc[:, -1].sub(df1.iloc[:, 0]).dt.total_seconds() 
print (df['diff']) 
0  0.0 
1 1786.0 
2  4.0 
Name: diff, dtype: float64 
Verwandte Themen