Как интерполировать в Pandas, используя только предыдущие значения? - PullRequest
0 голосов
/ 08 февраля 2020

Это мой фрейм данных:

df = pd.DataFrame(np.array([ [1,5],[1,6],[1,np.nan],[2,np.nan],[2,8],[2,4],[2,np.nan],[2,10],[3,np.nan]]),columns=['id','value'])

  id   value
0  1    5
1  1    6
2  1    NaN
3  2    NaN
4  2    8
5  2    4
6  2    NaN
7  2    10
8  3    NaN

Это мой ожидаемый вывод:

  id   value
0  1    5
1  1    6
2  1    7
3  2    NaN
4  2    8
5  2    4
6  2    2
7  2    10
8  3    NaN

Это мой текущий вывод с использованием этого кода:

df.value.interpolate(method="krogh")

0     5.000000
1     6.000000
2     9.071429
3    10.171429
4     8.000000
5     4.000000
6     2.357143
7    10.000000
8    36.600000  

Здесь я хочу сделать две важные вещи:

идентификатор группы , а затем интерполировать, используя только выше значений не ниже значений строк

Ответы [ 3 ]

0 голосов
/ 08 февраля 2020

Текущий pandas .Series.interpolate не поддерживает то, что вы хотите, поэтому для достижения вашей цели вам нужно сделать 2 grouby's, что будет отвечать вашему желанию использовать только предыдущие строки. Идея заключается в следующем: объединить в одну группу только отсутствующее значение (!!!) и предыдущие строки (это может иметь ограничения, если в строке несколько пропущенных значений, но это хорошо подходит для вашего игрушечного примера)

Предположим, у нас есть df:

print(df)
   ID  Value
0   1    5.0
1   1    6.0
2   1    NaN
3   2    NaN
4   2    8.0
5   2    4.0
6   2    NaN
7   2   10.0
8   3    NaN

Затем мы объединяем все пропущенные значения в группе с предыдущими строками:

df["extrapolate"] = df.groupby("ID")["Value"].apply(lambda grp: grp.isnull().cumsum().shift().bfill())
print(df)
   ID  Value  extrapolate
0   1    5.0          0.0
1   1    6.0          0.0
2   1    NaN          0.0
3   2    NaN          1.0
4   2    8.0          1.0
5   2    4.0          1.0
6   2    NaN          1.0
7   2   10.0          2.0
8   3    NaN          NaN

Вы можете видеть, что при группировании по ["ID","extrapolate"] отсутствующее значение попадет в ту же группу, что и ненулевые значения предыдущих строк.

Теперь мы готовы выполнить экстраполяцию (с spline из order=1):

df.groupby(["ID","extrapolate"], as_index=False).apply(lambda grp:grp.interpolate(method="spline",order=1)).drop("extrapolate", axis=1)
    ID  Value
0  1.0    5.0
1  1.0    6.0
2  1.0    7.0
3  2.0    NaN
4  2.0    8.0
5  2.0    4.0
6  2.0    0.0
7  2.0   10.0
8  NaN    NaN

Надеюсь, это поможет.

0 голосов
/ 09 февраля 2020

Это должно сработать:

df["value_interp"]=df.value.combine_first(df.groupby("id")["value"].apply(lambda y: y.expanding().apply(lambda x: x.interpolate(method="krogh").to_numpy()[-1], raw=False)))

Выходы:

    id  value  value_interp
0  1.0    5.0           5.0
1  1.0    6.0           6.0
2  1.0    NaN           7.0
3  2.0    NaN           NaN
4  2.0    8.0           8.0
5  2.0    4.0           4.0
6  2.0    NaN           0.0
7  2.0   10.0          10.0
8  3.0    NaN           NaN

(интерполируется только на основе предыдущих значений в группе - следовательно, индекс 6 вернет 0 не 2)

0 голосов
/ 08 февраля 2020

Вы можете группировать по id, а затем по l oop по группам для выполнения интерполяции. Для id = 2 интерполяция не даст вам значения 2

import pandas as pd
import numpy as np

df = pd.DataFrame(np.array([ [1,5],[1,6],[1,np.nan],[2,np.nan],[2,8],[2,4],[2,np.nan],[2,10],[3,np.nan]]),columns=['id','value'])

data = []
for name, group in df.groupby('id'):
    group_interpolation = group.interpolate(method='krogh', limit_direction='forward', axis=0)
    data.append(group_interpolation)

df = (pd.concat(data)).round(1)

Вывод:

    id  value
0  1.0    5.0
1  1.0    6.0
2  1.0    7.0
3  2.0    NaN
4  2.0    8.0
5  2.0    4.0
6  2.0    4.7
7  2.0   10.0
8  3.0    NaN
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...