разбиение данных длины (метра) на интервалы с пандами


У меня есть фрейм данных интервальных данных (из скважин), который выглядит примерно так:

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

Мне нужно свернуть эти данные, но также разбить их на наименее распространенный интервал длины; в результате столбец " min "становится заголовком столбца, а значения - "рангом". Выходные данные будут выглядеть следующим образом:

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

Таким образом, в основном "от " и" до " описывают неперекрывающиеся интервалы вниз по скважине, где интервалы были разделены наименьшим общим знаменателем - как вы можно видеть, что интервал "py" из исходной таблицы был разделен, первый (0-5m) на py:2, cpy:0 и второй (5-10m) на py:2, cpy:3.5.

Результат работы только базовой функции pivot_table таков:

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

, который просто обрабатывает столбцы from и to, объединенные как индекс. Важным моментом является то, что мои выходные данные не могут иметь перекрытия от и до значений (т. е. последующее значение " от "не может быть меньше предыдущего значения "до").

Есть ли элегантный способ сделать это с помощью панд? Спасибо за помощь!

1 2

1 ответ:

Я не знаю естественной интервальной арифметики в Пандах, поэтому вам нужно сделать это. Вот способ сделать это, если я правильно понимаю связанные условия. Это может быть проблемой O (n^3), это создаст огромную таблицу для больших записей.

# 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"])

Для:

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