熊猫:快速向时间戳列添加可变数量的月份

2024-06-28 11:33:10 发布

您现在位置:Python中文网/ 问答频道 /正文

设置如下:

我有两个(整数索引)列,start和{}。start有时间戳(其内部类型是np.datetime64[ns]),而{}是整数。在

我希望快速生成一列,该列由start中的每个datetime组成,偏移量为month_delta中相应的月数。我该怎么做?在

我尝试过但没用的方法:

  • apply太慢。在
  • 不能将一系列DateOffset对象添加到一系列datetime64[ns]数据类型(或DatetimeIndex)中。在
  • 你也不能使用一系列的timedelta64对象;Pandas会自动地将基于月的时间增量转换为基于纳秒的时间增量,这些时间增量大约为30天。(哎呀!没有默默地失败会怎么样?)在

目前,我正在迭代month_delta的所有不同值,并对我创建的DatetimeIndex的相关部分执行tshift操作,但这是一个非常糟糕的代码:

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

恶心!有什么建议吗?在


Tags: 对象index时间mask整数start增量pd
3条回答

下面是一种方法(通过使用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)

收益率

^{2}$

如果不使用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,而不是{}模块或{}模块。既然你只是用应用程序创建delta,我希望你能体验一下加速。在

我想这样的方法可能会奏效:

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。。。在

相关问题 更多 >