Skip to main content
 首页 » 编程设计

python之仅使用 pandas 来填补空白,而不是在末端使用 NaN

2025年05月04日14xxx_UU

我有一些大约 8 个月的房价数据,跟踪房屋进入市场直至售出的价格。我想填补中间数据中的几个空白,但我想保留每个数据末尾的 NaN 不变。

举个简单的例子,假设我们的房子 1 在“第 4 天”以 200000 的价格上市,在“第 9 天”以 190000 的价格售出。我们有 house2 在第 1 天到第 12 天保持在 180000,并且在那个时间窗口内没有出售。但是,在第 6 天和第 7 天出了点问题,我丢失了数据:

house1 = [NaN, NaN, NaN, 200000, 200000, NaN, NaN, 200000, 190000, NaN, NaN, NaN] 
house2 = [180000, 180000, 180000, 180000, 180000, NaN, NaN, 180000, 180000, 180000, 180000, 180000] 

现在想象一下,这些不是常规数组,而是按日期索引的 Pandas Dataframes 中的列。

问题是,我通常用来填补空白的函数是 DataFrame.fillna()使用 backfill 或 ffill 方法。如果我使用 ffill,house1 返回这个:

house1 = [NaN, NaN, NaN, 200000, 200000, 200000, 200000, 200000, 190000, 190000, 190000, 190000] 

它填补了空白,但也错误地填补了销售日之后的数据。如果我改用回填,我会得到这个:

house1 = [200000, 200000, 200000, 200000, 200000, 200000, 200000, 200000, 190000, NaN, NaN, NaN] 

又是填补了空白,不过这次也是填补了数据的前端。如果我将 'limit=2' 与 ffill 一起使用,那么我得到的是:

house1 = [NaN, NaN, NaN, 200000, 200000, 200000, 200000, 200000, 190000, 190000, 190000, NaN] 

它再次填补了空白,但随后它也开始填充超出“真实”数据结束位置的数据。

到目前为止,我的解决方案是编写以下函数:

def fillGaps(houseDF): 
    """Fills up holes in the housing data""" 
 
    def fillColumns(column): 
        filled_col = column 
        lastValue = None 
        # Keeps track of if we are dealing with a gap in numbers 
        gap = False 
        i = 0 
        for currentValue in filled_col: 
            # Loops over all the nans before the numbers begin 
            if not isANumber(currentValue) and lastValue is None: 
                pass 
            # Keeps track of the last number we encountered before a gap 
            elif isANumber(currentValue) and (gap is False): 
                lastIndex = i 
                lastValue = currentValue 
            # Notes when we encounter a gap in numbers 
            elif not isANumber(currentValue): 
                gap = True 
            # Fills in the gap 
            elif isANumber(currentValue): 
                gapIndicies = range(lastIndex + 1, i) 
                for j in gapIndicies: 
                    filled_col[j] = lastValue 
                gap = False 
            i += 1 
        return filled_col 
 
    filled_df = houseDF.apply(fillColumns, axis=0) 
    return filled_df 

它只是跳过前面的所有 NaN,填充间隙(由实数值之间的 NaN 组定义),并且不填充最后的 NaN。

是否有更简洁的方法或我不知道的内置 pandas 函数?

请您参考如下方法:

我在一年后找到了这个答案,但需要它在具有多列的 DataFrame 上工作,所以我想把我的解决方案留在这里以防其他人需要相同的解决方案。我的功能只是YS-L的修改版

def fillna_downbet(df): 
    df = df.copy() 
    for col in df: 
        non_nans = df[col][~df[col].apply(np.isnan)] 
        start, end = non_nans.index[0], non_nans.index[-1] 
        df[col].loc[start:end] = df[col].loc[start:end].fillna(method='ffill') 
    return df 

谢谢!