diff --git a/doc/source/v0.15.0.txt b/doc/source/v0.15.0.txt index ca24eb3f910ed..ccea9de8bcbcf 100644 --- a/doc/source/v0.15.0.txt +++ b/doc/source/v0.15.0.txt @@ -192,6 +192,7 @@ Bug Fixes +- Bug in ``is_superperiod`` and ``is_subperiod`` cannot handle higher frequencies than ``S`` (:issue:`7760`, :issue:`7772`, :issue:`7803`) diff --git a/pandas/tseries/frequencies.py b/pandas/tseries/frequencies.py index fe61e5f0acd9b..073f6e13047e9 100644 --- a/pandas/tseries/frequencies.py +++ b/pandas/tseries/frequencies.py @@ -929,25 +929,31 @@ def is_subperiod(source, target): if _is_quarterly(source): return _quarter_months_conform(_get_rule_month(source), _get_rule_month(target)) - return source in ['D', 'C', 'B', 'M', 'H', 'T', 'S'] + return source in ['D', 'C', 'B', 'M', 'H', 'T', 'S', 'L', 'U', 'N'] elif _is_quarterly(target): - return source in ['D', 'C', 'B', 'M', 'H', 'T', 'S'] + return source in ['D', 'C', 'B', 'M', 'H', 'T', 'S', 'L', 'U', 'N'] elif target == 'M': - return source in ['D', 'C', 'B', 'H', 'T', 'S'] + return source in ['D', 'C', 'B', 'H', 'T', 'S', 'L', 'U', 'N'] elif _is_weekly(target): - return source in [target, 'D', 'C', 'B', 'H', 'T', 'S'] + return source in [target, 'D', 'C', 'B', 'H', 'T', 'S', 'L', 'U', 'N'] elif target == 'B': - return source in ['B', 'H', 'T', 'S'] + return source in ['B', 'H', 'T', 'S', 'L', 'U', 'N'] elif target == 'C': - return source in ['C', 'H', 'T', 'S'] + return source in ['C', 'H', 'T', 'S', 'L', 'U', 'N'] elif target == 'D': - return source in ['D', 'H', 'T', 'S'] + return source in ['D', 'H', 'T', 'S', 'L', 'U', 'N'] elif target == 'H': - return source in ['H', 'T', 'S'] + return source in ['H', 'T', 'S', 'L', 'U', 'N'] elif target == 'T': - return source in ['T', 'S'] + return source in ['T', 'S', 'L', 'U', 'N'] elif target == 'S': - return source in ['S'] + return source in ['S', 'L', 'U', 'N'] + elif target == 'L': + return source in ['L', 'U', 'N'] + elif target == 'U': + return source in ['U', 'N'] + elif target == 'N': + return source in ['N'] def is_superperiod(source, target): @@ -982,25 +988,31 @@ def is_superperiod(source, target): smonth = _get_rule_month(source) tmonth = _get_rule_month(target) return _quarter_months_conform(smonth, tmonth) - return target in ['D', 'C', 'B', 'M', 'H', 'T', 'S'] + return target in ['D', 'C', 'B', 'M', 'H', 'T', 'S', 'L', 'U', 'N'] elif _is_quarterly(source): - return target in ['D', 'C', 'B', 'M', 'H', 'T', 'S'] + return target in ['D', 'C', 'B', 'M', 'H', 'T', 'S', 'L', 'U', 'N'] elif source == 'M': - return target in ['D', 'C', 'B', 'H', 'T', 'S'] + return target in ['D', 'C', 'B', 'H', 'T', 'S', 'L', 'U', 'N'] elif _is_weekly(source): - return target in [source, 'D', 'C', 'B', 'H', 'T', 'S'] + return target in [source, 'D', 'C', 'B', 'H', 'T', 'S', 'L', 'U', 'N'] elif source == 'B': - return target in ['D', 'C', 'B', 'H', 'T', 'S'] + return target in ['D', 'C', 'B', 'H', 'T', 'S', 'L', 'U', 'N'] elif source == 'C': - return target in ['D', 'C', 'B', 'H', 'T', 'S'] + return target in ['D', 'C', 'B', 'H', 'T', 'S', 'L', 'U', 'N'] elif source == 'D': - return target in ['D', 'C', 'B', 'H', 'T', 'S'] + return target in ['D', 'C', 'B', 'H', 'T', 'S', 'L', 'U', 'N'] elif source == 'H': - return target in ['H', 'T', 'S'] + return target in ['H', 'T', 'S', 'L', 'U', 'N'] elif source == 'T': - return target in ['T', 'S'] + return target in ['T', 'S', 'L', 'U', 'N'] elif source == 'S': - return target in ['S'] + return target in ['S', 'L', 'U', 'N'] + elif source == 'L': + return target in ['L', 'U', 'N'] + elif source == 'U': + return target in ['U', 'N'] + elif source == 'N': + return target in ['N'] def _get_rule_month(source, default='DEC'): diff --git a/pandas/tseries/tests/test_frequencies.py b/pandas/tseries/tests/test_frequencies.py index 37371b5828c8c..10a8286f4bec9 100644 --- a/pandas/tseries/tests/test_frequencies.py +++ b/pandas/tseries/tests/test_frequencies.py @@ -342,6 +342,16 @@ def test_is_superperiod_subperiod(): assert(fmod.is_superperiod(offsets.Hour(), offsets.Minute())) assert(fmod.is_subperiod(offsets.Minute(), offsets.Hour())) + assert(fmod.is_superperiod(offsets.Second(), offsets.Milli())) + assert(fmod.is_subperiod(offsets.Milli(), offsets.Second())) + + assert(fmod.is_superperiod(offsets.Milli(), offsets.Micro())) + assert(fmod.is_subperiod(offsets.Micro(), offsets.Milli())) + + assert(fmod.is_superperiod(offsets.Micro(), offsets.Nano())) + assert(fmod.is_subperiod(offsets.Nano(), offsets.Micro())) + + if __name__ == '__main__': import nose nose.runmodule(argv=[__file__, '-vvs', '-x', '--pdb', '--pdb-failure'], diff --git a/pandas/tseries/tests/test_plotting.py b/pandas/tseries/tests/test_plotting.py index 0bdba3751b6fd..5742b8e9bfaae 100644 --- a/pandas/tseries/tests/test_plotting.py +++ b/pandas/tseries/tests/test_plotting.py @@ -707,6 +707,28 @@ def test_from_weekly_resampling(self): for l in ax.get_lines(): self.assertTrue(PeriodIndex(data=l.get_xdata()).freq.startswith('W')) + @slow + def test_mixed_freq_second_millisecond(self): + # GH 7772, GH 7760 + idxh = date_range('2014-07-01 09:00', freq='S', periods=50) + idxl = date_range('2014-07-01 09:00', freq='100L', periods=500) + high = Series(np.random.randn(len(idxh)), idxh) + low = Series(np.random.randn(len(idxl)), idxl) + # high to low + high.plot() + ax = low.plot() + self.assertEqual(len(ax.get_lines()), 2) + for l in ax.get_lines(): + self.assertEqual(PeriodIndex(data=l.get_xdata()).freq, 'L') + tm.close() + + # low to high + low.plot() + ax = high.plot() + self.assertEqual(len(ax.get_lines()), 2) + for l in ax.get_lines(): + self.assertEqual(PeriodIndex(data=l.get_xdata()).freq, 'L') + @slow def test_irreg_dtypes(self): # date