Python 如何在数据框中移动日期(添加x个月)?
我有一个带有日期列的数据框 我知道如何按固定的月数移动日期(例如,在第x列中的所有日期上加上3个月);然而,我不知道如何将日期按月份进行移动,这不是固定的,而是数据帧的另一列 有什么想法吗 我复制了下面的一个最小示例。我得到的错误是:Python 如何在数据框中移动日期(添加x个月)?,python,date,pandas,Python,Date,Pandas,我有一个带有日期列的数据框 我知道如何按固定的月数移动日期(例如,在第x列中的所有日期上加上3个月);然而,我不知道如何将日期按月份进行移动,这不是固定的,而是数据帧的另一列 有什么想法吗 我复制了下面的一个最小示例。我得到的错误是: The truth value of a Series is ambiguous 非常感谢 import pandas as pd import numpy as np import datetime df = pd.DataFrame() df['year'
The truth value of a Series is ambiguous
非常感谢
import pandas as pd
import numpy as np
import datetime
df = pd.DataFrame()
df['year'] = np.arange(2000,2010)
df['month'] = 3
df['mydate'] = pd.to_datetime( (df.year * 10000 + df.month * 100 +1).apply(str), format='%Y%m%d')
df['month shift'] = np.arange(0,10)
# if I want to shift mydate by 3 months, I can convert it to DatetimeIndex and use dateOffset:
df['my date shifted by 3 months'] = pd.DatetimeIndex( df['mydate'] ) + pd.DateOffset(months = 3)
# however, how do I shift mydate by the number of months in the column 'month shift'?
#This does NOT work:
df['my date shifted'] = pd.DatetimeIndex( df['mydate'] ) + pd.DateOffset(months = df['month shift'])
print df
IIUC您可以使用轴=1的
应用:
In [23]: df.apply(lambda x: x['mydate'] + pd.DateOffset(months = x['month shift']), axis=1)
Out[23]:
0 2000-03-01
1 2001-04-01
2 2002-05-01
3 2003-06-01
4 2004-07-01
5 2005-08-01
6 2006-09-01
7 2007-10-01
8 2008-11-01
9 2009-12-01
dtype: datetime64[ns]
Edchorn的解决方案确实比Anton Protopov的答案快得多,事实上,在我的用例中,它的执行时间是毫秒,而应用程序的执行时间是分钟。问题是Edchorn在评论中发布的解决方案给出了稍微不正确的结果。在示例中:
import pandas as pd
import numpy as np
import datetime
df = pd.DataFrame()
df['year'] = np.arange(2000,2010)
df['month'] = 3
df['mydate'] = pd.to_datetime((df.year * 10000 + df.month * 100 + 1).apply(str), format='%Y%m%d')
df['month shift'] = np.arange(0,10)
答案是:
df['my date shifted'] = df['mydate'] + pd.TimedeltaIndex( df['month shift'], unit='M')
给出:
可通过以下方法获得正确的溶液:
def set_to_month_begin(series):
#Following doesn't work:
# res = series.dt.floor("MS")
#This also doesn't work (it fails in case the date is already the first day of the month):
# res = series - pd.offsets.MonthBegin(1)
res = pd.to_datetime(series).dt.normalize()
res = res - pd.to_timedelta(res.dt.day - 1, unit='d')
return res
def add_months(df, date_col, months_num_col):
"""This function adds the number of months specified per each row in `months_num_col` to date in `date_col`.
This method is *significantly* faster than:
df.apply(lambda x: x[date_col] + pd.DateOffset(months = x[months_num_col]), axis=1)
"""
number_of_days_in_avg_month = 365.24 / 12
time_delta = pd.TimedeltaIndex(df[months_num_col] * number_of_days_in_avg_month + 10, unit='D')
return set_to_month_begin(df[date_col] + time_delta)
df['my date shifted'] = add_months(df, 'mydate', 'month shift')
这将产生以下结果:
“一”衬板使用:
df['my date shift']=(
df[“mydate”].values.astype(“datetime64[M]”)
+df[“月移”].values.astype(“timedelta64[M]”)
)
不确定这是否是您想要的:df['mydate shift']=df['mydate']+pd.TimedeltaIndex(df['month shift'],unit='M')
?您可以添加预期的输出吗?@EdChum,您的建议有效,谢谢!然而,究竟为什么你的代码有效而我的代码无效?它是否在任何地方都有记录,或者熊猫的语法在约会时是极其反复无常的?与Matlab和SQL相比,我在语法和文档中都找不到任何一致性,我正在构造一个timedeltaindex并添加另一个系列,pd.DateOffset
只构造一个标量DateOffset
对象,它不能构造一个系列。请注意,第二行的日期可能不是您想要的,因此我的问题实际上我没有注意到。这是因为熊猫把一个月变为30天吗?理想情况下不是,我需要2001年3月1日+1个月才能成为2001年4月1日;这些标题需要精确,因为我需要按它们分组。你的代码可以调整以得到这个结果吗?谢谢。这是可行的,但EdChum的解决方案似乎更快;我想这可能是因为运行apply语句的速度比较慢。方法是矢量化的,因为它构造了一个索引并将其添加到另一个系列中,但它可能不是您想要的,因为2001-03-31
,我已经解释过了。因为我的数据帧不是很大,所以现在我将使用Anton的解决方案。我确实想知道是否有一种方法可以矢量化——当安东的代码应用于大型数据帧时,使其更快。伙计们,非常感谢你们两个!