假设我有o1=pdandas.tseries.frequencies.to_offset('M')
(MonthEnd
对象(和o2=pdandas.tseries.frequencies.to_offset('Y')
(YearEnd
对象(。
如何计算1个o2
中有多少个o1
?
所以在我的例子中,我应该得到数字12,这意味着在1个YearEnd
(Y
或A
(周期中有12个MonthEnd
(M
(周期。
在Day
(D
(和Week
(W
(之间,我应该得到数字7。
在QuarterEnd
(Q
(和YearEnd
(Y
或A
(之间,我应该得到数字4。
等等…
最简单的是固定频率。在这里,您可以简单地使用.nanos
:
>>> m = pd.tseries.frequencies.to_offset('5min')
>>> n = pd.tseries.frequencies.to_offset('1h')
>>> n.nanos / m.nanos
12.0
对于非固定频率,这会引发一个错误:
>>> y = pd.tseries.frequencies.to_offset('1Y')
>>> y.nanos
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "pandas/_libs/tslibs/offsets.pyx", line 690, in pandas._libs.tslibs.offsets.BaseOffset.nanos.__get__
ValueError: <YearEnd: month=12> is a non-fixed frequency
你总是可以使用一个特定的日期来找出这个频率可以转换为时间增量:
>>> d = pd.Timestamp(0)
>>> (d + y) - d
Timedelta('364 days 00:00:00')
>>> ((d + y) - d).delta
31449600000000000
当然,按照频率不固定的定义,用这种方法划分这些纳秒并不能得到确切的结果。然而,它应该足够接近四舍五入:
>>> yns = ((d + y) - d).delta
>>> qns = ((d + q) - d).delta
>>> q = pd.tseries.frequencies.to_offset('1Q')
>>> yns / qns
4.089887640449438
>>> round(yns / qns)
4
然后你当然可以验证这个四舍五入的结果是否适用于你选择的开始日期:
>>> d + q * 4 == d + y
True
当然,计算日期的选择很重要,如果你不是从一月份开始,4个季度并不总是与1年相匹配:
>>> d = pd.Timestamp('1970-4-01')
>>> d + q * 4 == d + y
False
因此,如果你使用多年的频率,这是需要记住的。
def div_offsets(a, b, date=pd.Timestamp(0)):
''' Compute pandas dateoffset ratios using nanosecond conversion
'''
try:
return a.nanos / b.nanos
except ValueError:
pass
ans = ((date + a) - date).delta
bns = ((date + b) - date).delta
if ans > bns:
ratio = round(ans / bns)
assert date + ratio * b == date + a
return ratio
else:
ratio = round(bns / ans)
assert date + b == date + ratio * a
return 1 / ratio
想不出一种直接的方法,但您可以尝试利用pandas.date_range
:
def get_ratio(offset_a, offset_b, rounding=False):
START = pd.Timestamp.today() # any random day
LARGER_OFFSET = offset_a if START+offset_a > START+offset_b else offset_b
freq_a = pd.date_range(START-LARGER_OFFSET, START+LARGER_OFFSET,
freq=offset_a, closed='left').size
freq_b = pd.date_range(START-LARGER_OFFSET, START+LARGER_OFFSET,
freq=offset_b, closed='left').size
return freq_a / freq_b
offset = pd.tseries.frequencies.to_offset
>>> get_ratio(offset('M'), offset('Y'))
12
>>> get_ratio(offset('Q'), offset('Y'))
4
>>> get_ratio(offset('D'), offset('W'))
7