如何有效地从python中的日期中减去年份?
Posted
技术标签:
【中文标题】如何有效地从python中的日期中减去年份?【英文标题】:How to efficiently subtract years from dates in python? 【发布时间】:2022-01-09 23:28:29 【问题描述】:我在 Python 中从 date column
减去 years
,感觉比 R 慢很多,通常情况并非如此,所以我想知道在 python 中是否有更快/更有效的方法?
(在 R 工作多年后,我将回到 python,所以我的 Python 技能不再好,正在寻找 Python 中的代码优化)。
python代码:
import numpy as np
import pandas as pd
import datetime as dt
import time
我在下面显示的数据只是用来说明我正在使用的date format
(行数在我的原始数据中是:466285)。
df = pd.DataFrame('date_str': ['Apr-84','Mar-66','May-85'])
df['date'] = pd.to_datetime(df['date_str'], format = '%b-%y')
由于我在年份方面得到了一些错误的日期,例如 year: 2066, 2085
等,所以写了一个小函数来根据我的需要更正日期:
# year subtraction function
def date_correction(x):
if x > pd.to_datetime('2017-12-01'):
x = (x - pd.to_timedelta(100 * 365.24, unit='d'))
else:
x = x
return x
start = time.time()
df['date'] = df['date'].apply(date_correction)
end = time.time()
print("Time taken: ", end - start)
Time taken: 32.958526611328125
我认为时间以秒为单位,因为完成此过程花费了很多时间,这使我也不得不在 R 中计时。
R代码:
library(tidyverse)
library(lubridate)
library(microbenchmark)
df = data.frame(date_str = c('Apr-84','Mar-66','May-85'))
df <- df %>%
mutate(date = lubridate::my(date_str))
减法和时间运算:
mbm <- microbenchmark( 'date_subt' =
df <- df %>%
mutate(date = if_else(
df$date > ymd('2017-12-01'),
df$date %m-% years(100),
df$date
))
)
mbm
结果:
Unit: milliseconds
expr min lq mean median uq max neval
date_subt 324.3357 331.2416 372.4745 338.8745 396.3026 744.4625 100
autplot(mbm)
【问题讨论】:
我能看到的第一个优化是在函数之外计算 2017-12-01 和 100 年的日期时间对象。这样做会使计算速度提高 10 倍左右(使用数据框中的 100000 个元素进行测试)。 我只是在python
中寻找 vectorized
方法,因为 R & python 时间执行存在巨大差异,这让我对我的方法感到好奇。
【参考方案1】:
您可以尝试使用 timedelta 运行您的代码吗?
像这样:
from datetime import timedelta
if dt > pd.to_datetime('2017-12-01'):
dt -= timedelta(years=100)
【讨论】:
我在尝试dt -= timedelta(years=100)
时遇到错误,因为没有参数年,所以尝试使用天数:x -= dt.timedelta(days=100 * 365.24)
又花了 Time taken: 32.42573404312134
秒。感谢您向我建议这种方法,但这也比 R 操作慢很多
好吧.. 我认为 Corralien 方法是最佳实践【参考方案2】:
使用布尔掩码和DateOffset
的矢量化方式:
df.update(df.loc[df['date'] > '2017-12-01', 'date'] - pd.DateOffset(years=100)
更简洁的方式(不带update
)
df.loc[df['date'] > '2017-12-01', 'date'] -= pd.DateOffset(years=100)
【讨论】:
谢谢@Corralien,我想通过使用.apply()
我已经在python
中对其进行了矢量化,但我想我错了。再次感谢分享代码。感谢您的帮助!
不幸的是,apply
是一种方便的循环方式(几乎)
是的,你是对的!!
这次花了Time taken: 0.00697779655456543
秒。以上是关于如何有效地从python中的日期中减去年份?的主要内容,如果未能解决你的问题,请参考以下文章
如何从 Java 8 Date API 中的回历日期中减去回历年份