2017-07-03 2 views
2

Ich habe einen Datenrahmen von Längenintervalldaten (aus Bohrungen), die etwa wie folgt aussieht:Spaltlänge (m) Daten durch Intervall mit Pandas

df 
Out[46]: 
    from to min intensity 
0  0 10 py  2 
1  5 15 cpy  3.5 
2 14 27 spy  0.7 

Ich brauche diese Daten zu schwenken, sondern auch brechen auf dem kleinsten gemeinsamen Längenintervall; Die Spalte "min" wird als Spaltenüberschrift angezeigt, und die Werte sind der "Rang". Die Ausgabe würde wie folgt aussehen:

df.somefunc(index=['from','to'], columns='min', values='intensity', fill_value=0) 
Out[47]: 
    from to py cpy spy 
0  0 5 2 0 0 
1  5 10 2 3.5 0 
2 10 14 0 3.5 0 
3 14 15 0 3.5 0.7 
4 15 27 0 0 0.7 

so im Grunde die „From“ und „To“ beschreiben nicht überlappende Intervalle ein Bohrloch nach unten, wobei die Intervalle durch den kleinsten gemeinsamen Nenner geteilt wurden - wie Sie das sehen können "py" Intervall von der ursprünglichen Tabelle wurde aufgeteilt, die erste (0-5m) in py: 2, cpy: 0 und die zweite (5-10m) in py: 2, cpy: 3.5.

Das Ergebnis aus nur eine grundlegenden pivot_table Funktion ist folgende:

pd.pivot_table(df, values='intensity', index=['from', 'to'], columns="min", aggfunc="first", fill_value=0) 
Out[48]: 
min  cpy py spy 
from to    
0 10 0 2 0 
5 15 3.5 0 0 
14 27 0 0 0.75 

, die nur die als Index in Kombination von und zu Spalten behandelt. Ein wichtiger Punkt ist, dass meine Ausgabe keine Überlappung von und zu Werten haben kann (IE der nachfolgende 'von' Wert kann nicht kleiner als der vorherige 'to' Wert sein).

Gibt es eine elegante Möglichkeit, dies mit Pandas zu erreichen? Danke für die Hilfe!

Antwort

1

Ich kenne keine natürliche Intervallarithmetik in Pandas, also müssen Sie es tun. Hier ein Weg, das zu tun, wenn ich gebundene Bedingungen richtig verstehe. Dies kann ein O (n^3) Problem sein, es wird eine riesige Tabelle für große Einträge erstellen.

# make the new bounds 
bounds=np.unique(np.hstack((df["from"],df["to"]))) 
df2=pd.DataFrame({"from":bounds[:-1],"to":bounds[1:]}) 

#find inclusions 
isin=df.apply(lambda x : 
df2['from'].between(x[0],x[1]-1) 
| df2['to'].between(x[0]+1,x[1]) 
,axis=1).T 

#data 
data=np.where(isin,df.intensity,0) 

#result 
df3=pd.DataFrame(data, 
pd.MultiIndex.from_arrays(df2.values.T),df["min"]) 

Für:

In [26]: df3 
Out[26]: 
min  py cpy spy 
0 5 2.0 0.0 0.0 
5 10 2.0 3.5 0.0 
10 14 0.0 3.5 0.0 
14 15 0.0 3.5 0.7 
15 27 0.0 0.0 0.7 
+0

Wow, das ist eigentlich viel weniger Codezeilen dann würde ich dachte, es zu nehmen. Vielen Dank!!! –

Verwandte Themen