diff --git a/doc/source/release.rst b/doc/source/release.rst index 4ddf125905204..80274c74c0f87 100644 --- a/doc/source/release.rst +++ b/doc/source/release.rst @@ -80,6 +80,8 @@ API Changes - ``week,dayofweek,dayofyear,quarter`` - ``microsecond,nanosecond,qyear`` - ``min(),max()`` + - ``pd.infer_freq()`` +- ``pd.infer_freq()`` will now raise a ``TypeError`` if given an invalid ``Series/Index`` type (:issue:`6407`) Experimental Features ~~~~~~~~~~~~~~~~~~~~~ diff --git a/doc/source/v0.14.0.txt b/doc/source/v0.14.0.txt index 84232359e99a4..949de3f674028 100644 --- a/doc/source/v0.14.0.txt +++ b/doc/source/v0.14.0.txt @@ -42,6 +42,7 @@ API changes - ``week,dayofweek,dayofyear,quarter`` - ``microsecond,nanosecond,qyear`` - ``min(),max()`` + - ``pd.infer_freq()`` .. ipython:: python diff --git a/pandas/tseries/frequencies.py b/pandas/tseries/frequencies.py index 398e428e45c79..8d925231625cb 100644 --- a/pandas/tseries/frequencies.py +++ b/pandas/tseries/frequencies.py @@ -13,7 +13,6 @@ import pandas.lib as lib import pandas.tslib as tslib - class FreqGroup(object): FR_ANN = 1000 FR_QTR = 2000 @@ -637,22 +636,28 @@ def infer_freq(index, warn=True): Parameters ---------- index : DatetimeIndex + if passed a Series will use the values of the series (NOT THE INDEX) warn : boolean, default True Returns ------- freq : string or None None if no discernible frequency + TypeError if the index is not datetime-like """ - from pandas.tseries.index import DatetimeIndex - - if not isinstance(index, DatetimeIndex): - from pandas.tseries.period import PeriodIndex - if isinstance(index, PeriodIndex): - raise ValueError("PeriodIndex given. Check the `freq` attribute " - "instead of using infer_freq.") - index = DatetimeIndex(index) - + import pandas as pd + + if isinstance(index, com.ABCSeries): + values = index.values + if not (com.is_datetime64_dtype(index.values) or values.dtype == object): + raise TypeError("cannot infer freq from a non-convertible dtype on a Series of {0}".format(index.dtype)) + index = values + if isinstance(index, pd.PeriodIndex): + raise TypeError("PeriodIndex given. Check the `freq` attribute " + "instead of using infer_freq.") + if not isinstance(index, pd.DatetimeIndex) and isinstance(index, pd.Index): + raise TypeError("cannot infer freq from a non-convertible index type {0}".format(type(index))) + index = pd.DatetimeIndex(index) inferer = _FrequencyInferer(index, warn=warn) return inferer.get_freq() diff --git a/pandas/tseries/tests/test_frequencies.py b/pandas/tseries/tests/test_frequencies.py index 3e8600af36f79..ca88515cc0a89 100644 --- a/pandas/tseries/tests/test_frequencies.py +++ b/pandas/tseries/tests/test_frequencies.py @@ -7,7 +7,7 @@ import numpy as np -from pandas import Index, DatetimeIndex, Timestamp, date_range, period_range +from pandas import Index, DatetimeIndex, Timestamp, Series, date_range, period_range from pandas.tseries.frequencies import to_offset, infer_freq from pandas.tseries.tools import to_datetime @@ -72,7 +72,7 @@ def test_to_offset_negative(): freqstr = '-5min10s' result = to_offset(freqstr) assert(result.n == -310) - + def test_to_offset_leading_zero(): freqstr = '00H 00T 01S' @@ -101,7 +101,7 @@ class TestFrequencyInference(tm.TestCase): def test_raise_if_period_index(self): index = PeriodIndex(start="1/1/1990", periods=20, freq="M") - self.assertRaises(ValueError, infer_freq, index) + self.assertRaises(TypeError, infer_freq, index) def test_raise_if_too_few(self): index = _dti(['12/31/1998', '1/3/1999']) @@ -269,6 +269,44 @@ def test_non_datetimeindex(self): result = infer_freq(vals) self.assertEqual(result, rng.inferred_freq) + def test_invalid_index_types(self): + + # test all index types + for i in [ tm.makeIntIndex(10), + tm.makeFloatIndex(10), + tm.makeStringIndex(10), + tm.makeUnicodeIndex(10), + tm.makePeriodIndex(10) ]: + self.assertRaises(TypeError, lambda : infer_freq(i)) + + def test_series(self): + + # GH6407 + # inferring series + + # invalid type of Series + for s in [ Series(np.arange(10)), + Series(np.arange(10.))]: + self.assertRaises(TypeError, lambda : infer_freq(s)) + + # a non-convertible string + self.assertRaises(ValueError, lambda : infer_freq(Series(['foo','bar']))) + + # cannot infer on PeriodIndex + for freq in [None, 'MS', 'Y']: + s = Series(period_range('2013',periods=10,freq=freq)) + self.assertRaises(TypeError, lambda : infer_freq(s)) + + # DateTimeIndex + for freq in ['MS', 'L', 'S']: + s = Series(date_range('20130101',periods=10,freq=freq)) + inferred = infer_freq(s) + self.assertEqual(inferred,freq) + + s = Series(date_range('20130101','20130110')) + inferred = infer_freq(s) + self.assertEqual(inferred,'D') + MONTHS = ['JAN', 'FEB', 'MAR', 'APR', 'MAY', 'JUN', 'JUL', 'AUG', 'SEP', 'OCT', 'NOV', 'DEC']