Интерполировать (или экстраполировать) только небольшие пробелы в кадре данных панд

У меня есть pandas DataFrame со временем как индекс (1 мин. Freq) и несколько столбцов данных. Иногда данные содержат NaN. Если это так, я хочу интерполировать только в том случае, если разрыв не превышает 5 минут. В этом случае это будет максимум 5 последовательных NaN. Данные могут выглядеть так (несколько тестовых примеров, которые показывают проблемы):

import numpy as np import pandas as pd from datetime import datetime start = datetime(2014,2,21,14,50) data = pd.DataFrame(index=[start + timedelta(minutes=1*x) for x in range(0, 8)], data={'a': [123.5, np.NaN, 136.3, 164.3, 213.0, 164.3, 213.0, 221.1], 'b': [433.5, 523.2, 536.3, 464.3, 413.0, 164.3, 213.0, 221.1], 'c': [123.5, 132.3, 136.3, 164.3] + [np.NaN]*4, 'd': [np.NaN]*8, 'e': [np.NaN]*7 + [2330.3], 'f': [np.NaN]*4 + [2763.0, 2142.3, 2127.3, 2330.3], 'g': [2330.3] + [np.NaN]*7, 'h': [2330.3] + [np.NaN]*6 + [2777.7]}) 

Он читается следующим образом:

 In [147]: data Out[147]: abcdefgh 2014-02-21 14:50:00 123.5 433.5 123.5 NaN NaN NaN 2330.3 2330.3 2014-02-21 14:51:00 NaN 523.2 132.3 NaN NaN NaN NaN NaN 2014-02-21 14:52:00 136.3 536.3 136.3 NaN NaN NaN NaN NaN 2014-02-21 14:53:00 164.3 464.3 164.3 NaN NaN NaN NaN NaN 2014-02-21 14:54:00 213.0 413.0 NaN NaN NaN 2763.0 NaN NaN 2014-02-21 14:55:00 164.3 164.3 NaN NaN NaN 2142.3 NaN NaN 2014-02-21 14:56:00 213.0 213.0 NaN NaN NaN 2127.3 NaN NaN 2014-02-21 14:57:00 221.1 221.1 NaN NaN 2330.3 2330.3 NaN 2777.7 

Я знаю data.interpolate() но у него есть несколько недостатков, так как он дает этот результат, что хорошо для столбцов ae, но для столбцов fh это не удается по разным причинам ::

  abcdefg \ 2014-02-21 14:50:00 123.5 433.5 123.5 NaN NaN NaN 2330.3 2014-02-21 14:51:00 129.9 523.2 132.3 NaN NaN NaN 2330.3 2014-02-21 14:52:00 136.3 536.3 136.3 NaN NaN NaN 2330.3 2014-02-21 14:53:00 164.3 464.3 164.3 NaN NaN NaN 2330.3 2014-02-21 14:54:00 213.0 413.0 164.3 NaN NaN 2763.0 2330.3 2014-02-21 14:55:00 164.3 164.3 164.3 NaN NaN 2142.3 2330.3 2014-02-21 14:56:00 213.0 213.0 164.3 NaN NaN 2127.3 2330.3 2014-02-21 14:57:00 221.1 221.1 164.3 NaN 2330.3 2330.3 2330.3 h 2014-02-21 14:50:00 2330.300000 2014-02-21 14:51:00 2394.214286 2014-02-21 14:52:00 2458.128571 2014-02-21 14:53:00 2522.042857 2014-02-21 14:54:00 2585.957143 2014-02-21 14:55:00 2649.871429 2014-02-21 14:56:00 2713.785714 2014-02-21 14:57:00 2777.700000 

f) Вначале разрыв состоит из NaN в 4 минуты, их следует заменить на это значение 2763,0 (т.е. экстраполяция назад во времени)

g) Разрыв длится более 5 минут, но все же он экстраполируется

h) Разрыв длится более 5 минут, но промежуток интерполируется.

Я понимаю эти причины, конечно, я нигде не указал, что он не должен интерполировать более длинные промежутки времени, чем 5 минут. Я понимаю, что interpolate только экстраполирует вперед во времени, но я хочу, чтобы она также экстраполировала назад во времени. Есть ли какие-либо известные методы, которые я могу использовать для своей проблемы, не изобретая колесо?

Изменить: метод data.interpolate принимает limit входного параметра, которое определяет максимальное количество последовательных NaN для замены интерполяцией. Но это все еще интерполирует до предела, но я хочу продолжить все NaN в этом случае.

One Solution collect form web for “Интерполировать (или экстраполировать) только небольшие пробелы в кадре данных панд”

Итак, вот маска, которая должна решить проблему. Просто interpolate а затем примените маску для сброса соответствующих значений в NaN. Честно говоря, это было немного больше работы, чем я понял, это было бы потому, что мне пришлось перебирать каждый столбец, но затем группа не работала без меня, предоставляя некоторые фиктивные столбцы, такие как «те».

Во всяком случае, я могу объяснить, если что-то неясно, но на самом деле только несколько строк трудно понять. См. Здесь немного больше объяснений трюка на линии df['new'] или просто распечатывайте отдельные строки, чтобы лучше видеть, что происходит.

 mask = data.copy() for i in list('abcdefgh'): df = pd.DataFrame( data[i] ) df['new'] = ((df.notnull() != df.shift().notnull()).cumsum()) df['ones'] = 1 mask[i] = (df.groupby('new')['ones'].transform('count') < 5) | data[i].notnull() In [7]: data Out[7]: abcdefgh 2014-02-21 14:50:00 123.5 433.5 123.5 NaN NaN NaN 2330.3 2330.3 2014-02-21 14:51:00 NaN 523.2 132.3 NaN NaN NaN NaN NaN 2014-02-21 14:52:00 136.3 536.3 136.3 NaN NaN NaN NaN NaN 2014-02-21 14:53:00 164.3 464.3 164.3 NaN NaN NaN NaN NaN 2014-02-21 14:54:00 213.0 413.0 NaN NaN NaN 2763.0 NaN NaN 2014-02-21 14:55:00 164.3 164.3 NaN NaN NaN 2142.3 NaN NaN 2014-02-21 14:56:00 213.0 213.0 NaN NaN NaN 2127.3 NaN NaN 2014-02-21 14:57:00 221.1 221.1 NaN NaN 2330.3 2330.3 NaN 2777.7 In [8]: mask Out[8]: abcdefgh 2014-02-21 14:50:00 True True True False False True True True 2014-02-21 14:51:00 True True True False False True False False 2014-02-21 14:52:00 True True True False False True False False 2014-02-21 14:53:00 True True True False False True False False 2014-02-21 14:54:00 True True True False False True False False 2014-02-21 14:55:00 True True True False False True False False 2014-02-21 14:56:00 True True True False False True False False 2014-02-21 14:57:00 True True True False True True False True 

Это легко оттуда, если вы не сделаете ничего интересного в отношении экстраполяции:

 In [9]: data.interpolate().bfill()[mask] Out[9]: abcdefgh 2014-02-21 14:50:00 123.5 433.5 123.5 NaN NaN 2763.0 2330.3 2330.3 2014-02-21 14:51:00 129.9 523.2 132.3 NaN NaN 2763.0 NaN NaN 2014-02-21 14:52:00 136.3 536.3 136.3 NaN NaN 2763.0 NaN NaN 2014-02-21 14:53:00 164.3 464.3 164.3 NaN NaN 2763.0 NaN NaN 2014-02-21 14:54:00 213.0 413.0 164.3 NaN NaN 2763.0 NaN NaN 2014-02-21 14:55:00 164.3 164.3 164.3 NaN NaN 2142.3 NaN NaN 2014-02-21 14:56:00 213.0 213.0 164.3 NaN NaN 2127.3 NaN NaN 2014-02-21 14:57:00 221.1 221.1 164.3 NaN 2330.3 2330.3 NaN 2777.7 

Редактировать, чтобы добавить: Вот более быстрая (около 2x по этим образцам данных) и немного более простой способ, перемещая некоторые вещи за пределы цикла:

 mask = data.copy() grp = ((mask.notnull() != mask.shift().notnull()).cumsum()) grp['ones'] = 1 for i in list('abcdefgh'): mask[i] = (grp.groupby(i)['ones'].transform('count') < 5) | data[i].notnull() 
  • Почему .loc ведет себя по-разному в зависимости от того, печатаются или назначены значения?
  • Количество наиболее часто встречающихся 100 слов из предложений в Dataframe Pandas
  • как я могу преобразовать дескрипторы, имеющие среднее значение по центру и масштабируемое до единичной дисперсии до моделирования машинного обучения с использованием python и pandas
  • Почему pandas.DataFrame.apply печатает хлам?
  • Как суммировать и означать один DataFrame для создания другого DataFrame
  • Объединение таблицы / DataFrames с общим столбцом в Python
  • Как вставлять данные в ноутбук IPython?
  • Как изменить документ по срокам dataframe в dataframe, который записывает документы, в которых появляется слово
  •  
    Interesting Posts for Van-Lav

    Нейронная сеть XOR gate не изучает

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

    Как сортировать (список / кортеж) списков / кортежей?

    bpython-подобный автозаполнение и описание параметров в Emacs Python Mode?

    Как изменить размер шрифта тиков объекта axes в matplotlib

    Отправка пакетов из pcap с измененным src / dst в scapy

    Как языки сценариев используют сокеты?

    pandas: извлечение определенных выбранных столбцов из DataFrame в новый DataFrame

    Проверьте, доступен ли элемент в селене

    В Python существует ли асинхронный эквивалент многопроцессорной или параллельной.futures?

    Как убедиться, что файл существует или может быть создан до его написания в Python?

    Два модуля Python требуют содержимого друг друга – может ли это работать?

    повторно импортировать модуль-под-тестом, чтобы потерять контекст

    Попытка понять python с помощью операторов и контекстных менеджеров

    Как отредактировать стиль заголовка в Treeview (Python ttk)

    Python - лучший язык программирования в мире.