描述时间序列中的缺口 pandas

4 投票
1 回答
4297 浏览
提问于 2025-04-18 13:47

我正在尝试写一个函数,这个函数可以处理连续的时间序列,并返回一个数据结构,用来描述数据中任何缺失的部分(比如一个包含“开始”和“结束”列的数据框)。这似乎是时间序列中一个比较常见的问题,但我尝试了很多方法,比如用groupby、diff等,甚至在StackOverflow上查找资料,结果还是没能找到比下面更好的解决方案。

对我来说,使用向量化操作来保持效率是很重要的。我相信应该有更明显的解决方案可以使用向量化操作,不是吗?感谢大家的帮助。

import pandas as pd


def get_gaps(series):
    """
    @param series: a continuous time series of data with the index's freq set
    @return: a series where the index is the start of gaps, and the values are
         the ends
    """
    missing = series.isnull()
    different_from_last = missing.diff()

    # any row not missing while the last was is a gap end        
    gap_ends = series[~missing & different_from_last].index

    # count the start as different from the last
    different_from_last[0] = True

    # any row missing while the last wasn't is a gap start
    gap_starts = series[missing & different_from_last].index        

    # check and remedy if series ends with missing data
    if len(gap_starts) > len(gap_ends):
         gap_ends = gap_ends.append(series.index[-1:] + series.index.freq)

    return pd.Series(index=gap_starts, data=gap_ends)

顺便说一下,我使用的版本是 Pandas==0.13.1,Numpy==1.8.1,Python 2.7

1 个回答

2

这个问题可以转化为在一个列表中寻找连续的数字。你需要找到所有序列为零的索引,如果有一段连续的数字,比如(3,4,5,6)都是零,那么你只需要提取开始和结束的位置,也就是(3,6)。

import numpy as np
import pandas as pd
from operator import itemgetter
from itertools import groupby


# create an example 
data = [2, 3, 4, 5, 12, 13, 14, 15, 16, 17]
s = pd.series( data, index=data)
s = s.reindex(xrange(18))
print find_gap(s)  


def find_gap(s): 
    """ just treat it as a list
    """ 
    nullindex = np.where( s.isnull())[0]
    ranges = []
    for k, g in groupby(enumerate(nullindex), lambda (i,x):i-x):
        group = map(itemgetter(1), g)
        ranges.append((group[0], group[-1]))
    startgap, endgap = zip(* ranges) 
    return pd.series( endgap, index= startgap )

参考链接:识别列表中连续数字的组

撰写回答