首页 > 解决方案 > 如何伪造丢失的间隔记录?

问题描述

我有一个 DataFrame,它由不规则时间间隔内发生的变化组成。

例如


ID   YEAR ADDRESS
ABC  2015 123 Meadow Ln
ABC  2017 66 Sycamore ST
EFG  2017 99 Morris St

我想创建一系列平衡的时间间隔,如下所示 -

ABC  2015 123 Meadow Ln
ABC  2016 123 Meadow Ln
ABC  2017 66 Sycamore ST
ABC  2018 66 Sycamore ST
ABC  2019 66 Sycamore ST
EFG  2017 99 Morris St
EFG  2018 99 Morris St
EFG  2019 99 Morris St

在我假设的第二步中,我也想向后传播..

所以....

ID   YEAR  ADDRESS
ABC  2013  123 Meadow Ln
ABC  2014  123 Meadow Ln
ABC  2015  123 Meadow Ln
ABC  2016  123 Meadow Ln
ABC  2017  66 Sycamore ST
ABC  2018  66 Sycamore ST
ABC  2019  66 Sycamore ST
EFG  2013  99 Morris St
EFG  2014  99 Morris St
EFG  2015  99 Morris St
EFG  2016  99 Morris St
EFG  2017  99 Morris St
EFG  2018  99 Morris St
EFG  2019  99 Morris St

最后,当我这样做时,我还希望能够跟踪真实/虚假记录,最终的 DataFrame 可能应该看起来像——


ID   YEAR  ADDRESS         ORIGINAL_RECORD
ABC  2013  123 Meadow Ln   False
ABC  2014  123 Meadow Ln   False
ABC  2015  123 Meadow Ln   True
ABC  2016  123 Meadow Ln   False
ABC  2017  66 Sycamore ST  True
ABC  2018  66 Sycamore ST  False
ABC  2019  66 Sycamore ST  False
EFG  2013  99 Morris St    False
EFG  2014  99 Morris St    False
EFG  2015  99 Morris St    False
EFG  2016  99 Morris St    False
EFG  2017  99 Morris St    True
EFG  2018  99 Morris St    False
EFG  2019  99 Morris St    False

有没有一种直接/惯用的方式来做到这一点?

编辑:我更新了示例以包含一个 ID 列。

标签: pythonpandasdataframe

解决方案


reindexfillna(method=...)结合使用

def fill_missing_years(df):
    return (
        df.set_index("YEAR")
        .reindex(range(2013, 2020))
        .assign(
            ORIGINAL_RECORD=lambda x: ~x.isna().any(axis=1)
        )  # set ORIGINAL_RECORD flag
        .fillna(method="ffill")
        .fillna(method="bfill")
        .reset_index()
    )

df.groupby("id").apply(fill_missing_years).reset_index(drop=True)

关于 ORIGINAL_RECORD 的注意事项:

reindex用值填充新行NaN,因此我们可以使用isna()方法来计算掩码 nan/not-nan。在一般情况下,它返回一个布尔数据帧:

>>> df = pd.DataFrame({"a": [None, 1, None], "b": [2, None, None]})
>>> df.isna()
True  False
False True
True  True

any()所以我们必须使用或all()沿第一个轴将这个 DataFrame 折叠成一列:

>>> df.isna().all(axis=1)
False
False
True

最后,如果行中的所有列都不是,我们使用反转 ('~') 来返回 True nan


推荐阅读