使用pandas填补间隙,而不是结束处的NaN值

2024-09-27 01:29:48 发布

您现在位置:Python中文网/ 问答频道 /正文

我有一些住房价格数据,跨度约8个月,并跟踪价格随着房子上市,直到出售。中间的数据有一些空白,我想填补,但我想让每一个NAN的末尾保持不变。在

举一个简单的例子,假设我们的房子1在“第4天”以20万英镑的价格上市,在“第9天”以19万英镑的价格售出。我们的房子2在第1-12天停留在18万英镑,在这个时间窗口内没有出售。但是,第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数据帧中按日期索引的列。在

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

^{pr2}$

这填补了空白,但也错误地填充了销售日之后的数据。如果我使用回填,我得到这样的结果:

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

同样,它填补了空白,但这次它也填补了数据的前端。如果我对ffill使用'limit=2',那么我得到的是:

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。在

有没有一种更干净的方法,或者一种我不知道的内置熊猫功能?在


Tags: the数据in价格colnan空白gap
3条回答

另一种解决多列数据帧的方法

df.fillna(method='ffill') + (df.fillna(method='bfill') * 0)

它是如何工作的?在

第一个fillna执行值的前向填充。这几乎是我们想要的,除了在每个系列的末尾留下填充值的痕迹。在

第二个fillna对乘以0的值进行反向填充。结果是我们不需要的尾随值将为NaN,其他值都将为0。在

最后,我们利用x+0=x和x+NaN=NaN这一事实将两者相加。在

您可以在本系列的某些部分使用fillna。根据您的描述,fillna应该只填充第一个non-NaN之后和最后一个non-NaN之前的NaN:

import numpy as np
import pandas as pd


def fill_column(house):
    house = house.copy()
    non_nans = house[~house.apply(np.isnan)]
    start, end = non_nans.index[0], non_nans.index[-1]
    house.ix[start:end] = house.ix[start:end].fillna(method='ffill')
    return house


house1 = pd.Series([np.nan, np.nan, np.nan, 200000, 200000, np.nan, np.nan, 200000, 190000, np.nan, np.nan, np.nan])
print fill_column(house1)

输出:

^{pr2}$

注意,这假设序列至少包含两个非nan,对应于第一天和最后一天的价格。在

我在一年后找到了这个答案,但是需要它来处理一个包含多个列的数据帧,所以我想把我的解决方案留在这里,以防其他人也需要这个答案。我的功能只是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

谢谢!在

相关问题 更多 >

    热门问题