2017-12-05 15 views
0

Ich habe ein Pandas Datenframe, wobei jede Spalte die y-Werte einer absteigenden Linie von 1 bis 0 darstellt und die Indizes die X-Werte darstellen. Jetzt bin ich daran interessiert, die Schnittpunkte zwischen diesen Linien und einer gegebenen Konstante (linear interpoliert) zu finden.Pandas Spalten Linie Schnittpunkt

Beispiel des gewünschten Ausgangs:

>>> df = pd.DataFrame({'y1': [1, .7, .4, .1, 0], 
         'y2': [1, .9, .7, .3, 0], 
         'y3': [1, .6, .3, .2, 0], 
         'y4': [1, .7, .5, .3, 0]}, index=[0, 10, 20, 30, 40]) 
>>> xs = get_intersection(df, .5) 
>>> xs 
{'x1': 16.6667, # = scipy.interpolate.interp1d([.7, .4], [10, 20])(.5) 
'x2': 25.0,  # =     interp1d([.7, .3], [20, 30])(.5) 
'x3': 13.3332, # =     interp1d([.6, .3], [10, 20])(.5) 
'x4': 20}  # No interpolation required 

Meine Daten bestehen aus etwa 400 Zeilen und Spalten 50.000.


mögliche Lösung:

Ich fand this SO answer, dass die Schnittpunkte zwischen zwei Zeilen mit dem folgende Verfahren findet:

idx = np.argwhere(np.diff(np.sign(f - g)) != 0).reshape(-1) + 0 

Ich denke, kann dies mit meinem Datenrahmen arbeiten eingestellt werden, aber Ich bin mir nicht sicher, wie hier vorzugehen ist:

>>> idx = np.argwhere(np.diff(np.sign(df - .5), axis=0) != 0) 
>>> idx 
array([[1, 0], 
     [1, 2], 
     [1, 3], 
     [2, 1], 
     [2, 3]], dtype=int64) 

Da die Menschen die Frage falsch zu verstehen scheinen, ich bin daran interessiert, diese Punkte bei der Suche nach:

enter image description here

, die durch lineare Interpolation der beiden nächsten Punkte zu finden sind.


Lösung: BM gab mir einen Schritt in die richtige Richtung:

def get_intersection(df, c): 
    dfind = len(df) - df.loc[::-1].apply(np.searchsorted, args=(c,), raw=True) 

    result = {} 
    for i, v in enumerate(dfind): 
     result[df.columns.values[i]] = interp1d([df.iloc[v][i], df.iloc[v - 1][i]], [df.index[v], df.index[v - 1]])(.5) 

    return result 


>>> get_intersection(df, .5) 
{'y1': array(16.666666666666668), 'y2': array(25.0), 'y3': array(13.333333333333332), 'y4': array(20.0)} 
+0

Ich bin verwirrt, was willst du jetzt von uns? – Dark

+0

Ich bin mir nicht sicher, wie ich 'idx' verwenden kann, um die Werte von 'ys' zu finden. Oder wenn die Methode, um 'idx' zu bekommen unnötig kompliziert ist, eine andere Möglichkeit, 'ys' zu berechnen. – Jurgy

+1

Die Indizes des ersten Punktes finden Sie mit 'dfind = len (df) -df.loc [:: - 1] .apply (np.searchsorted, args = (0.5,), raw = True)'. Atter das tun es durch eine Schleife. –

Antwort

1

da Sie 1D-Funktion (interp1d) benötigen, Schleifen sind so klar, lesen Sie einfach zu, und die Geschwindigkeit als Pandas Funktionen. verwenden np.searchsorted das gute Segment zu finden:

d = dict() 
ind=df.index.values 
for k,v in df.iteritems(): 
    y=v.values 
    i=len(y)-np.searchsorted(y[::-1],0.5) #indices 
    sl = slice(i-1,i+1) 
    d[k]= +scipy.interpolate.interp1d(v[sl],ind[sl])(.5) 

print (pd.Series(d)) 

# y1 16.666667 
# y2 25.000000 
# y3 13.333333 
# y4 20.000000 
# dtype: float64 

Wahrscheinlich abgestimmt werden muss dies, wenn kein Schnittpunkt vorhanden ist.