2016-05-05 24 views
3

ich einen Datenrahmen mit den folgenden Informationen haben:Pandas Interpolation innerhalb eines groupby

filename val1 val2 
t     
1 file1.csv 5  10 
2 file1.csv NaN  NaN 
3 file1.csv 15  20 
6 file2.csv NaN  NaN 
7 file2.csv 10  20 
8 file2.csv 12  15 

Ich möchte die Werte in der Datenrahmen auf den Indizes basieren auf interpolieren, aber nur innerhalb jeder Dateigruppe.

zu interpolieren, die ich normalerweise

df = df.interpolate(method="index") 

Und Gruppe tun würde, ich

grouped = df.groupby("filename") 

ich die interpoliert Datenrahmen wie folgt aussehen möchte:

filename val1 val2 
t     
1 file1.csv 5  10 
2 file1.csv 10  15 
3 file1.csv 15  20 
6 file2.csv NaN  NaN 
7 file2.csv 10  20 
8 file2.csv 12  15 

Wo Die NaNs sind immer noch bei t = 6 vorhanden, da sie die ersten Elemente in der file2-Gruppe sind.

Ich vermute, ich muss verwenden „anwenden“, aber nicht in der Lage, genau herauszufinden, wie ...

grouped.apply(interp1d) 
... 
TypeError: __init__() takes at least 3 arguments (2 given) 

Jede Hilfe würde geschätzt.

Antwort

4
>>> df.groupby('filename').apply(lambda group: group.interpolate(method='index')) 
    filename val1 val2 
t      
1 file1.csv  5 10 
2 file1.csv 10 15 
3 file1.csv 15 20 
6 file2.csv NaN NaN 
7 file2.csv 10 20 
8 file2.csv 12 15 
+0

Dies scheint auf einem kleinen Datenframe zu funktionieren, dauert aber eine * lange * Zeit auf einem großen (um Größenordnungen mehr Zeit als bei Verwendung von .interpolate()). Würden Sie erwarten, dass die Effizienz so viel schlechter ist? Die Anzahl der Gruppen ist klein im Vergleich zur Anzahl der Zeilen (etwa 1000 Gruppen im Vergleich zu 10^7 Zeilen). –

0

Ich lief auch in diese. Statt apply zu verwenden, können Sie transform verwenden, die um mehr als 25% Ihrer Laufzeit zu reduzieren, wenn Sie in der Größenordnung von 1000 Gruppen haben:

import numpy as np 
import pandas as pd 

np.random.seed(500) 
test_df = pd.DataFrame({ 
    'a': np.random.randint(low=0, high=1000, size=10000), 
    'b': np.random.choice([1, 2, 4, 7, np.nan], size=10000, p=([0.2475]*4 + [0.01])) 
}) 

Tests:

%timeit test_df.groupby('a').transform(pd.DataFrame.interpolate) 

Ausgang: 566 ms ± 27.1 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)

%timeit test_df.groupby('a').apply(pd.DataFrame.interpolate) 

Ausgang: 788 ms ± 10.4 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)

%timeit test_df.groupby('a').apply(lambda group: group.interpolate()) 

Ausgang: 787 ms ± 17.9 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)

%timeit test_df.interpolate() 

Ausgang: 918 µs ± 16.9 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)

Sie werden noch eine deutliche Steigerung der Laufzeit im Vergleich zu einem voll vektorisiert Aufruf interpolate auf dem vollen Datenrahmen sehen, aber ich weiß nicht denke du kannst viel besser in Pandas machen.