对于可以使用下面的代码导出的示例数据帧,我想更新列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.

我想执行矢量化方法,所以我try 了以下方法,结果不正确.

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())

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

Desired Output

+------------+-------------+
|    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  |
+------------+-------------+

推荐答案

This is the purpose of Pandas' merge_asof function.
We have to be specific about which columns are going where. This will work as a left join and in this case, we want 'offset_date' to represent the "left". Then, for each value in 'offset_date', we look for the greatest value in 'date' that does not exceed that value in '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方法DOES NOT覆盖数据帧,那么我们可以看到它,并且您需要使用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

Python相关问答推荐

如何从不同长度的HTML表格中抓取准确的字段?

在Python中使用一行try

socket.gaierror:[Errno -2]名称或服务未知|Firebase x Raspberry Pi

Image Font生成带有条形码Code 128的条形码时出现枕头错误OSErsor:无法打开资源

在应用循环中间保存pandas DataFrame

Python中的负前瞻性regex遇到麻烦

剧作家Python:expect(locator).to_be_visible()vs locator.wait_for()

Odoo -无法比较使用@api.depends设置计算字段的日期

Python Hashicorp Vault库hvac创建新的秘密版本,但从先前版本中删除了密钥

比较2 PD.数组的令人惊讶的结果

如何让剧作家等待Python中出现特定cookie(然后返回它)?

ODE集成中如何终止solve_ivp的无限运行

cv2.matchTemplate函数匹配失败

合并帧,但不按合并键排序

python—telegraph—bot send_voice发送空文件

Gunicorn无法启动Flask应用,因为无法将应用解析为属性名或函数调用.'"'' "

Odoo16:模板中使用的docs变量在哪里定义?

pandas:在操作pandora之后将pandora列转换为int

不允许 Select 北极滚动?

如何在Python 3.9.6和MacOS Sonoma 14.3.1下安装Pyregion