Pandas将列值替换为Last available值



对于可以使用下面的代码派生的示例数据帧,我希望更新列Offset_Date,以便对于列Offset_Date中不在列Date中的任何日期,我希望用列Date中的最后可用值替换Offset_Date中的日期。

data = {"date": ['2021-01-01', '2021-01-03', '2021-01-04', '2021-01-05',
'2021-01-07', '2021-01-09', '2021-01-10', '2021-01-11'],
"offset_date": ['2021-01-02', '2021-01-04', '2021-01-05',
'2021-01-06', '2021-01-08', '2021-01-10',
'2021-01-11', '2021-01-12']}
test_df = pd.DataFrame(data)
test_df['date'] = pd.to_datetime(test_df['date'])
test_df['offset_date'] = pd.to_datetime(test_df['offset_date'])

为了进一步解释,在上述数据帧的第一行中,日期2021-01-02不在列date内,所以我想用列date中的最后可用值(即2021-01-01(替换该值。

我想执行矢量化方法,所以我尝试了以下操作,结果不正确。

test_df['offset_date_upd'] = np.where(test_df['offset_date'] in test_df['date'].values,
test_df['offset_date'], 
test_df[test_df['date'] <= test_df['offset_date']].values.max())

如何使用矢量化方法获得以下所需的输出?

所需输出

+------------+-------------+
|    Date    | Offset_Date |
+------------+-------------+
| 2021-01-01 | 2021-01-01  |
| 2021-03-01 | 2021-04-01  |
| 2021-04-01 | 2021-05-01  |
| 2021-05-01 | 2021-05-01  |
| 2021-07-01 | 2021-07-01  |
| 2021-09-01 | 2021-10-01  |
| 2021-10-01 | 2021-11-01  |
| 2021-11-01 | 2021-11-01  |
+------------+-------------+

IIUC,可以使用isinmaskfillna:

test_df['offset_date'] = (test_df['offset_date']
.where(test_df['offset_date'].isin(test_df['date']),
test_df['date'])
)

输出:

date offset_date
0 2021-01-01  2021-01-01
1 2021-01-03  2021-01-04
2 2021-01-04  2021-01-05
3 2021-01-05  2021-01-05
4 2021-01-07  2021-01-07
5 2021-01-09  2021-01-10
6 2021-01-10  2021-01-11
7 2021-01-11  2021-01-11

这就是Pandasmerge_asof函数的目的
我们必须明确哪些列要去哪里。这将作为左联接工作,在这种情况下,我们希望'offset_date'表示";左";。然后,对于'offset_date'中的每个值,我们在'date'中寻找不超过'offset_date'中的最大值。

这种方法中的一个问题是,两列都需要排序。如果这是真实数据的问题,请告诉我,我会在底部添加一个处理此问题的部分。

new_offset_date = pd.merge_asof(
test_df[['offset_date']],  # limit `test_df` to just the column I need for the merge
test_df[['date']],         # limit `test_df` to just the other column I need
left_on=['offset_date'],   # name the columns since they have different names
right_on=['date']          # name the other column as well
)['date']

现在新日期在pandas.Series中,如果我们使用assign方法,我们可以看到它,不会覆盖您的数据帧,并且您需要使用test_df = test_df.assign(offset_date=new_offset_date)将新日期实际保留在数据帧中。

test_df.assign(offset_date=new_offset_date)
date offset_date
0 2021-01-01  2021-01-01
1 2021-01-03  2021-01-04
2 2021-01-04  2021-01-05
3 2021-01-05  2021-01-05
4 2021-01-07  2021-01-07
5 2021-01-09  2021-01-10
6 2021-01-10  2021-01-11
7 2021-01-11  2021-01-11

下面的方法应该适用于您的案例

test_df["offset_date"] = np.where(
test_df.offset_date.isin(test_df.date),
test_df.offset_date,
test_df.date
)

相关内容

  • 没有找到相关文章

最新更新