Линейная интерполяция NaN в кадре данных pandas на основе двух его соседей (сверху и снизу или слева и справа)

У меня есть фрейм данных с одним столбцом значений с плавающей запятой и отметкой времени в качестве индекса, аналогичного приведенному ниже. Все метки времени в индексе сортируются в порядке возрастания.

timestamp           value
2014-01-08 08:00:42 1
2014-01-08 08:01:00 NaN
2014-01-08 08:01:12 3
2014-01-08 08:01:52 7
2014-01-08 08:02:02 9

Как мне линейно интерполировать/ввести значение NaN, основанное «только» на значении 1 и 3 (т.е. выше и ниже значения). Фрейм данных огромен и может достигать 2 ГБ. Так что скорость важна для этой операции

Спасибо


person Ravi M    schedule 19.09.2017    source источник
comment
Вы видели stackoverflow.com/questions/25234782/?   -  person Zero    schedule 19.09.2017
comment
Я не знаю о функции прокатки в pandas df. Поэтому я не мог искать по этому параметру. Спасибо, что указали на эту ссылку. Выглядит очень актуально для моих вопросов. Спасибо   -  person Ravi M    schedule 19.09.2017
comment
Я просто хочу добавить к вопросу, что временные метки не с равными интервалами. Они сильно различаются. Таким образом, интерполяция также основана на метке времени и на том, насколько далеко и близко они находятся.   -  person Ravi M    schedule 19.09.2017


Ответы (1)


Изменить: вы обновили свой вопрос для интерполяции на основе различий временных меток в индексе, применяя эти пропорции к вашим значениям DataFrame.

Вот грубый способ сделать это, который на самом деле должен быть прилично быстрым:

ts = pd.to_datetime(['2014-01-08 08:00:42',
                     '2014-01-08 08:01:00',
                     '2014-01-08 08:01:12',
                     '2014-01-08 08:01:52',
                     '2014-01-08 08:02:02'])

df = pd.DataFrame([1, np.nan, 3, 7, 9], index=ts, columns=['value'])
td = df.index.to_series().diff().dt.total_seconds()
interp = df.value.shift(1) + (df.value.shift(-1) - df.value.shift(1)) \
       * td / (td.shift(-1) + td)

df['value'] = df['value'].fillna(interp)
print(df)
                     value
2014-01-08 08:00:42    1.0
2014-01-08 08:01:00    2.2
2014-01-08 08:01:12    3.0
2014-01-08 08:01:52    7.0
2014-01-08 08:02:02    9.0

В этом примере NaN во второй позиции имеет разницу во времени на 18 единиц ниже и на 12 единиц выше соответственно. Поэтому его следует заполнить значением 1 + (3 - 1) * (18 / (18 + 12)).

Вы также можете упростить эту математику.

Еще одна вещь: работая над этим ответом, я задал собственный вопрос о расчете временных дельт. У @piRSquared есть более быстрое решение здесь, если для вас важна скорость.

person Brad Solomon    schedule 19.09.2017
comment
Спасибо. Я внес несколько изменений в функцию вменения, которую вы указали ранее, попросив ее ссылаться на индекс (то есть время) и интерполировать на основе расстояния между временами. Это сработало очень хорошо, и код выглядит чистым :) - person Ravi M; 25.09.2017