以下是设置:
我有两个(整数索引)列,start
和month_delta
。 start
有时间戳(其内部类型为np.datetime64[ns]
),month_delta
为整数。
我希望快速生成由start
中的每个日期时间组成的列,并偏移month_delta
中相应的月数。我该怎么做?
我尝试过的东西不起作用:
apply
太慢了。DateOffset
个对象添加到一系列datetime64[ns]
dtype(或DatetimeIndex
)中。timedelta64
个对象;熊猫默默地将基于月份的timedeltas转换为基于纳秒的timedeltas,这个timedeltas长达30天。 (哎呀!没有失败的事情发生了什么?)目前,我正在迭代month_delta
的所有不同值,并在我创建的tshift
的相关部分上执行DatetimeIndex
,但这是可怕的 kludge:
new_dates = pd.Series(pd.Timestamp.now(), index=start.index)
date_index = pd.DatetimeIndex(start)
for i in xrange(month_delta.max()):
mask = (month_delta == i)
cur_dates = pd.Series(index=date_index[mask]).tshift(i, freq='M').index
new_dates[mask] = cur_dates
呸!有什么建议吗?
答案 0 :(得分:2)
这是一种方法(通过在timedelta64s中添加NumPy datetime64s)而不调用apply
:
import pandas as pd
import numpy as np
np.random.seed(1)
def combine64(years, months=1, days=1, weeks=None, hours=None, minutes=None,
seconds=None, milliseconds=None, microseconds=None, nanoseconds=None):
years = np.asarray(years) - 1970
months = np.asarray(months) - 1
days = np.asarray(days) - 1
types = ('<M8[Y]', '<m8[M]', '<m8[D]', '<m8[W]', '<m8[h]',
'<m8[m]', '<m8[s]', '<m8[ms]', '<m8[us]', '<m8[ns]')
vals = (years, months, days, weeks, hours, minutes, seconds,
milliseconds, microseconds, nanoseconds)
return sum(np.asarray(v, dtype=t) for t, v in zip(types, vals)
if v is not None)
def year(dates):
"Return an array of the years given an array of datetime64s"
return dates.astype('M8[Y]').astype('i8') + 1970
def month(dates):
"Return an array of the months given an array of datetime64s"
return dates.astype('M8[M]').astype('i8') % 12 + 1
def day(dates):
"Return an array of the days of the month given an array of datetime64s"
return (dates - dates.astype('M8[M]')) / np.timedelta64(1, 'D') + 1
N = 10
df = pd.DataFrame({
'start': pd.date_range('2000-1-25', periods=N, freq='D'),
'months': np.random.randint(12, size=N)})
start = df['start'].values
df['new_date'] = combine64(year(start), months=month(start) + df['months'],
days=day(start))
print(df)
产量
months start new_date
0 5 2000-01-25 2000-06-25
1 11 2000-01-26 2000-12-26
2 8 2000-01-27 2000-09-27
3 9 2000-01-28 2000-10-28
4 11 2000-01-29 2000-12-29
5 5 2000-01-30 2000-06-30
6 0 2000-01-31 2000-01-31
7 0 2000-02-01 2000-02-01
8 1 2000-02-02 2000-03-02
9 7 2000-02-03 2000-09-03
答案 1 :(得分:0)
我觉得这样的事情可能有用:
df['start'] = pd.to_datetime(df.start)
df.groupby('month_delta').apply(lambda x: x.start + pd.DateOffset(months=x.month_delta.iloc[0]))
可能有更好的方法来创建一系列DateOffset
个对象并添加一些方法,但是idk ......
答案 2 :(得分:0)
我没有找到办法,至少没有使用apply
进行设置,但假设没问题:
df = pandas.DataFrame(
[[datetime.date(2014,10,22), 1], [datetime.date(2014,11,20), 2]],
columns=['date','delta'])
>>> df
date delta
0 2014-10-22 1
1 2014-11-20 2
from dateutil.relativedelta import relativedelta
df['offset'] = df['delta'].apply(lambda x: relativedelta(months=x))
>>> df['date'] + df['offset']
0 2014-11-22
1 2015-01-20
请注意,您必须使用datetime
模块中的datetime
,而不是numpy
或pandas
模块。由于您只使用apply创建delta,我希望您能体验到加速。