给定一个日期时两个日期之间的月数



输入df

Date1            
2019-01-23      
2020-02-01  

注意:Date1的类型为datetime64[ns]

目标

我想计算Date1列和'2019-01-01'之间的月份差异。

Try and Ref

我尝试了这篇文章的答案,但失败如下:

df['Date1'].dt.to_period('M') - pd.to_datetime('2019-01-01').to_period('M') 
  • 注意:pandas版本:1.1.5

您的解决方案应该通过将句点转换为整数来更改,第二个值使用一个元素列表['2019-01-01']:

df['new'] = (df['Date1'].dt.to_period('M').astype(int) - 
pd.to_datetime(['2019-01-01']).to_period('M').astype(int))
print (df)
Date1  new
0 2019-01-23    0
1 2020-02-01   13

如果比较解决方案:

rng = pd.date_range('1900-04-03', periods=3000, freq='MS')
df = pd.DataFrame({'Date1': rng})  

In [106]: %%timeit
...: date_ref = pd.to_datetime('2019-01-01')
...: df["mo_since_2019_01"] = (df.Date1.dt.year - date_ref.year).values*12 + (df.Date1.dt.month - date_ref.month)
...: 
1.57 ms ± 8.18 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)
In [107]: %%timeit
...: df['new'] = (df['Date1'].dt.to_period('M').astype(int) - pd.to_datetime(['2019-01-01']).to_period('M').astype(int))
...: 
1.32 ms ± 19.2 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)

应用程序是引擎盖下的循环,因此速度较慢:

In [109]: %%timeit
...: start = pd.to_datetime("2019-01-01")
...: df['relative_months'] = df['Date1'].apply(lambda end: relative_months(start, end, freq="M"))
...: 
25.7 s ± 729 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)
In [110]: %%timeit
...: rd = df['Date1'].apply(lambda x:relativedelta(x,date(2019,1,1)))
...: mon = rd.apply(lambda x: ((x.years * 12) + x.months))
...: df['Diff'] = mon
...: 
94.2 ms ± 431 µs per loop (mean ± std. dev. of 7 runs, 10 loops each)

我认为这应该有效:

date_ref = pd.to_datetime('2019-01-01')
df["mo_since_2019_01"] = (df.Date1.dt.year - date_ref.year).values*12 + (df.Date1.dt.month - date_ref.month)
month_delta = (date2.year - date1.year)*12 + (date2.month - date1.month)

输出:

Date1  mo_since_2019_01
0 2019-01-23                 0
1 2020-02-01                13

使用此解决方案,您不需要进一步导入,因为它只需计算pd.date_range()在固定开始日期和可变结束日期之间的长度:

def relative_months(start, end, freq="M"):
if start < end:
x = len(pd.date_range(start=start,end=end,freq=freq))
else:
x = - len(pd.date_range(start=end,end=start,freq=freq))
return x
start = pd.to_datetime("2019-01-01")
df['relative_months'] = df['Date1'].apply(lambda end: relative_months(start, end, freq="M"))

在你的具体情况下,我认为anon01的解决方案应该是最快/最有利的;然而,我的变体允许对'M''D'等日期偏移使用通用频率字符串,并允许您专门处理";否定的";相对偏移(即,如果您的比较日期不早于Date1中的所有日期,会发生什么(。

尝试:

rd = df['Date1'].apply(lambda x:relativedelta(x,date(2019,1,1)))
mon = rd.apply(lambda x: ((x.years * 12) + x.months))
df['Diff'] = mon

输入:

Date1
0  2019-01-23
1  2020-02-01
2  2020-05-01
3  2020-06-01

输出:

Date1  Diff
0 2019-01-23     0
1 2020-02-01    13
2 2020-05-01    16
3 2020-06-01    17

最新更新