numpy和Pandas定时

2024-06-16 10:22:59 发布

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

在Python中,我有一个使用pandas生成(或从CSV文件中读取)的日期数组,我想在每个日期上添加一年。我可以用熊猫,但不能用纽比。我做错什么了?或者它是熊猫或纽比的虫子?在

谢谢!在

import numpy as np
import pandas as pd
from pandas.tseries.offsets import DateOffset

# Generate range of dates using pandas.
dates = pd.date_range('1980-01-01', '2015-01-01')

# Add one year using pandas.
dates2 = dates + DateOffset(years=1)

# Convert result to numpy. THIS WORKS!
dates2_np = dates2.values

# Convert original dates to numpy array.
dates_np = dates.values

# Add one year using numpy. THIS FAILS!
dates3 = dates_np + np.timedelta64(1, 'Y')

# TypeError: Cannot get a common metadata divisor for NumPy datetime metadata [ns] and [Y] because they have incompatible nonlinear base time units

Tags: importnumpyaddconvertpandasasnprange
2条回答

下面是它在numpy documentation中所说的:

There are two Timedelta units (‘Y’, years and ‘M’, months) which are treated specially, because how much time they represent changes depending on when they are used. While a timedelta day unit is equivalent to 24 hours, there is no way to convert a month unit into days, because different months have different numbers of days.

不过,几天和几周似乎很管用:

dates4 = dates_np + np.timedelta64(1, 'D')
dates5 = dates_np + np.timedelta64(1, 'W')

np.timedelta64(1, 'Y')添加到数据类型datetime64[ns]的数组中无效,因为一年并不对应于固定的纳秒数。有时一年是365天,有时是366天,有时甚至有额外的闰秒。(请注意,额外的闰秒,例如发生在2015-06-30 23:59:60的闰秒不能表示为NumPy datetime64s。)

我知道的向NumPy datetime64[ns]数组添加一年的最简单方法是将其分成若干部分,例如年、月和日,在整数数组上进行计算,然后重新组合datetime64数组:

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

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)

# break the datetime64 array into constituent parts
years, months, days = [f(dates_np) for f in (year, month, day)]
# recompose the datetime64 array after adding 1 to the years
dates3 = combine64(years+1, months, days)

收益率

^{pr2}$

尽管看起来有这么多代码,但实际上比添加日期偏移量1年要快:

In [206]: %timeit dates + DateOffset(years=1)
1 loops, best of 3: 285 ms per loop

In [207]: %%timeit
   .....: years, months, days = [f(dates_np) for f in (year, month, day)]
   .....: combine64(years+1, months, days)
   .....: 
100 loops, best of 3: 2.65 ms per loop

当然,pd.tseries.offsets提供了一整套偏移量,在使用NumPy datetime64时,这些偏移量没有简单的对应项

相关问题 更多 >