Pandas - 两个日期之间的月数
Pandas - Number of Months Between Two Dates
我认为这应该很简单,但我看到的是涉及迭代数据框日期字段以确定两个日期之间差异的技术。我遇到了麻烦。我熟悉 MSSQL DATEDIFF 所以我认为 Pandas datetime 会有类似的东西。我也许有,但我想念它。
是否有一种 Pandonic 方法可以将月数确定为两个日期(日期时间)之间的整数而不需要迭代?请记住,可能有数百万行,因此性能是一个考虑因素。
日期是日期时间对象,结果是这样的 - 新列是月份:
Date1 Date2 Months
2016-04-07 2017-02-01 11
2017-02-01 2017-03-05 1
这是一个非常简单的答案我的朋友:
df['nb_months'] = ((df.date2 - df.date1)/np.timedelta64(1, 'M'))
现在:
df['nb_months'] = df['nb_months'].astype(int)
df.assign(
Months=
(df.Date2.dt.year - df.Date1.dt.year) * 12 +
(df.Date2.dt.month - df.Date1.dt.month)
)
Date1 Date2 Months
0 2016-04-07 2017-02-01 10
1 2017-02-01 2017-03-05 1
另一种可能更优雅的解决方案是
df.Date2.dt.to_period('M') - df.Date1.dt.to_period('M')
,避免舍入错误。
时差有两种说法,在某种意义上都是正确的。让我们比较一下 7 月 31 日和 9 月 01 日之间的月份差异:
import numpy as np
import pandas as pd
dtr = pd.date_range(start="2016-07-31", end="2016-09-01", freq="D")
delta1 = int((dtr[-1] - dtr[0])/np.timedelta64(1,'M'))
delta2 = (dtr[-1].to_period('M') - dtr[0].to_period('M')).n
print(delta1,delta2)
使用 numpy 的 timedelta,delta1=1
,这是正确的,因为两者之间只有一个月,但 delta2=2
,这也是正确的,因为 9 月距离 7 月还有两个月。在大多数情况下,两者都会给出相同的答案,但根据上下文,一个可能比另一个更正确。
只是对@pberkes 回答的一小部分补充。
如果您希望答案为整数值并且 不是 pandas._libs.tslibs.offsets.MonthEnd,只需将 .n
附加到上述代码即可。
(pd.to_datetime('today').to_period('M') - pd.to_datetime('2020-01-01').to_period('M')).n
# [Out]:
# 7
这适用于 pandas 1.1.1:
df['Months'] = df['Date2'].dt.to_period('M').astype(int) - df['Date1'].dt.to_period('M').astype(int)
df
# Out[11]:
# Date1 Date2 Months
# 0 2016-04-07 2017-02-01 10
# 1 2017-02-01 2017-03-05 1
我认为这应该很简单,但我看到的是涉及迭代数据框日期字段以确定两个日期之间差异的技术。我遇到了麻烦。我熟悉 MSSQL DATEDIFF 所以我认为 Pandas datetime 会有类似的东西。我也许有,但我想念它。
是否有一种 Pandonic 方法可以将月数确定为两个日期(日期时间)之间的整数而不需要迭代?请记住,可能有数百万行,因此性能是一个考虑因素。
日期是日期时间对象,结果是这样的 - 新列是月份:
Date1 Date2 Months
2016-04-07 2017-02-01 11
2017-02-01 2017-03-05 1
这是一个非常简单的答案我的朋友:
df['nb_months'] = ((df.date2 - df.date1)/np.timedelta64(1, 'M'))
现在:
df['nb_months'] = df['nb_months'].astype(int)
df.assign(
Months=
(df.Date2.dt.year - df.Date1.dt.year) * 12 +
(df.Date2.dt.month - df.Date1.dt.month)
)
Date1 Date2 Months
0 2016-04-07 2017-02-01 10
1 2017-02-01 2017-03-05 1
另一种可能更优雅的解决方案是
df.Date2.dt.to_period('M') - df.Date1.dt.to_period('M')
,避免舍入错误。
时差有两种说法,在某种意义上都是正确的。让我们比较一下 7 月 31 日和 9 月 01 日之间的月份差异:
import numpy as np
import pandas as pd
dtr = pd.date_range(start="2016-07-31", end="2016-09-01", freq="D")
delta1 = int((dtr[-1] - dtr[0])/np.timedelta64(1,'M'))
delta2 = (dtr[-1].to_period('M') - dtr[0].to_period('M')).n
print(delta1,delta2)
使用 numpy 的 timedelta,delta1=1
,这是正确的,因为两者之间只有一个月,但 delta2=2
,这也是正确的,因为 9 月距离 7 月还有两个月。在大多数情况下,两者都会给出相同的答案,但根据上下文,一个可能比另一个更正确。
只是对@pberkes 回答的一小部分补充。
如果您希望答案为整数值并且 不是 pandas._libs.tslibs.offsets.MonthEnd,只需将 .n
附加到上述代码即可。
(pd.to_datetime('today').to_period('M') - pd.to_datetime('2020-01-01').to_period('M')).n
# [Out]:
# 7
这适用于 pandas 1.1.1:
df['Months'] = df['Date2'].dt.to_period('M').astype(int) - df['Date1'].dt.to_period('M').astype(int)
df
# Out[11]:
# Date1 Date2 Months
# 0 2016-04-07 2017-02-01 10
# 1 2017-02-01 2017-03-05 1