【问题标题】:Fill in dates in pandas dataframe based on previous rows根据前几行在 pandas 数据框中填写日期
【发布时间】:2019-05-20 18:09:20
【问题描述】:

我有以下数据框:

         date_one             date_two
2634    2018-05-22            None
2018    2017-06-22            2017-09-22
2706    2016-09-14            None
3018    2016-06-22            None

我想使用以下逻辑在date_two 列中填写日期:

  1. 如果date_two 列在该行中已有值,则不执行任何操作

  2. 对于date_one 列的第一行,请使用当前日期或date_one 列的 6 个月填写date_two 列,以较早者为准

  3. 对于所有其他行,使用当前行上方行中day_one 列中日期前一天的日期或当前当前行中date_one 日期后 6 个月填写 date_two 列行,以较早者为准

最终的结果是这样的:

         date_one             date_two
2634    2018-05-22            2018-11-18
2018    2017-06-22            2017-09-22
2706    2016-09-14            2017-03-13
3018    2016-06-22            2016-09-13

注意:date_two 的最后一列包含 2016-09-13,因为 2016-09-13 比该行上方 date_one 行中的日期早一天(规则 #2)。感谢@WeNYoBen。

我尝试使用iterrows,但不确定如何访问前一行的值

【问题讨论】:

  • date_two 的最后几列为什么是 2016-09-13 ?
  • @WeNYoBen 这是因为 2016-09-13 比该行上方 date_one 行中的日期早一天
  • 看第一行。 date_one2018-05-22,所以: 1. 当前日期是 2019-05-20。 2. date_one 6 个月后的日期是 2018-11-22。 3. 这两个较早的日期是2018-11-22。那么为什么预期输出中的 date_two2018-11-18?我认为,应该是 2018-11-22(规则 #2)。
  • @Valdi_Bo 感谢您指出这一点!6 个月,我的意思是 180 天,因为有些月有 31 天,date_two 的值与您认为的不同

标签: python pandas


【解决方案1】:

我假设两个日期列都是 DateTime 类型, 所以缺少 date_two 值实际上是 NaT,而不是 None

       date_one   date_two
2634 2018-05-22        NaT
2018 2017-06-22 2017-09-22
2706 2016-09-14        NaT
3018 2016-06-22        NaT

从计算辅助列开始 - date_one 从上一行开始:

df['date_one_prev'] = df.date_one.shift()

注意第一行date_one_prevNaT,很快就会用到。

然后定义一个函数应用于每一行:

def fn(row):
    if pd.isna(row.date_one_prev):  # First row
        return min(row.date_one + pd.DateOffset(180),
            pd.to_datetime('today'))
    elif pd.isna(row.date_two):     # NaT
        return min(row.date_one + pd.DateOffset(180),
            row.date_one_prev + pd.DateOffset(-1))
    else:    # date_two present
        return row.date_two

并进行实际处理,应用此功能:

df.date_two = df.apply(fn, axis=1)

唯一剩下要做的就是删除辅助列:

df.drop(columns=['date_one_prev'], inplace=True)

注意:根据您的评论,我使用 180 天 而不是 6 个月

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-06-17
    • 2018-05-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多