Skip to content

Commit 20b35fb

Browse files
committed
Merge pull request #6408 from jreback/freq_ops
API: pd.infer_freq interacts correctly with a Series
2 parents 3d9ef5a + 883d172 commit 20b35fb

File tree

4 files changed

+59
-13
lines changed

4 files changed

+59
-13
lines changed

doc/source/release.rst

+2
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,8 @@ API Changes
8080
- ``week,dayofweek,dayofyear,quarter``
8181
- ``microsecond,nanosecond,qyear``
8282
- ``min(),max()``
83+
- ``pd.infer_freq()``
84+
- ``pd.infer_freq()`` will now raise a ``TypeError`` if given an invalid ``Series/Index`` type (:issue:`6407`)
8385

8486
Experimental Features
8587
~~~~~~~~~~~~~~~~~~~~~

doc/source/v0.14.0.txt

+1
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@ API changes
4242
- ``week,dayofweek,dayofyear,quarter``
4343
- ``microsecond,nanosecond,qyear``
4444
- ``min(),max()``
45+
- ``pd.infer_freq()``
4546

4647
.. ipython:: python
4748

pandas/tseries/frequencies.py

+15-10
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,6 @@
1313
import pandas.lib as lib
1414
import pandas.tslib as tslib
1515

16-
1716
class FreqGroup(object):
1817
FR_ANN = 1000
1918
FR_QTR = 2000
@@ -637,22 +636,28 @@ def infer_freq(index, warn=True):
637636
Parameters
638637
----------
639638
index : DatetimeIndex
639+
if passed a Series will use the values of the series (NOT THE INDEX)
640640
warn : boolean, default True
641641
642642
Returns
643643
-------
644644
freq : string or None
645645
None if no discernible frequency
646+
TypeError if the index is not datetime-like
646647
"""
647-
from pandas.tseries.index import DatetimeIndex
648-
649-
if not isinstance(index, DatetimeIndex):
650-
from pandas.tseries.period import PeriodIndex
651-
if isinstance(index, PeriodIndex):
652-
raise ValueError("PeriodIndex given. Check the `freq` attribute "
653-
"instead of using infer_freq.")
654-
index = DatetimeIndex(index)
655-
648+
import pandas as pd
649+
650+
if isinstance(index, com.ABCSeries):
651+
values = index.values
652+
if not (com.is_datetime64_dtype(index.values) or values.dtype == object):
653+
raise TypeError("cannot infer freq from a non-convertible dtype on a Series of {0}".format(index.dtype))
654+
index = values
655+
if isinstance(index, pd.PeriodIndex):
656+
raise TypeError("PeriodIndex given. Check the `freq` attribute "
657+
"instead of using infer_freq.")
658+
if not isinstance(index, pd.DatetimeIndex) and isinstance(index, pd.Index):
659+
raise TypeError("cannot infer freq from a non-convertible index type {0}".format(type(index)))
660+
index = pd.DatetimeIndex(index)
656661
inferer = _FrequencyInferer(index, warn=warn)
657662
return inferer.get_freq()
658663

pandas/tseries/tests/test_frequencies.py

+41-3
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77

88
import numpy as np
99

10-
from pandas import Index, DatetimeIndex, Timestamp, date_range, period_range
10+
from pandas import Index, DatetimeIndex, Timestamp, Series, date_range, period_range
1111

1212
from pandas.tseries.frequencies import to_offset, infer_freq
1313
from pandas.tseries.tools import to_datetime
@@ -72,7 +72,7 @@ def test_to_offset_negative():
7272
freqstr = '-5min10s'
7373
result = to_offset(freqstr)
7474
assert(result.n == -310)
75-
75+
7676

7777
def test_to_offset_leading_zero():
7878
freqstr = '00H 00T 01S'
@@ -101,7 +101,7 @@ class TestFrequencyInference(tm.TestCase):
101101

102102
def test_raise_if_period_index(self):
103103
index = PeriodIndex(start="1/1/1990", periods=20, freq="M")
104-
self.assertRaises(ValueError, infer_freq, index)
104+
self.assertRaises(TypeError, infer_freq, index)
105105

106106
def test_raise_if_too_few(self):
107107
index = _dti(['12/31/1998', '1/3/1999'])
@@ -269,6 +269,44 @@ def test_non_datetimeindex(self):
269269
result = infer_freq(vals)
270270
self.assertEqual(result, rng.inferred_freq)
271271

272+
def test_invalid_index_types(self):
273+
274+
# test all index types
275+
for i in [ tm.makeIntIndex(10),
276+
tm.makeFloatIndex(10),
277+
tm.makeStringIndex(10),
278+
tm.makeUnicodeIndex(10),
279+
tm.makePeriodIndex(10) ]:
280+
self.assertRaises(TypeError, lambda : infer_freq(i))
281+
282+
def test_series(self):
283+
284+
# GH6407
285+
# inferring series
286+
287+
# invalid type of Series
288+
for s in [ Series(np.arange(10)),
289+
Series(np.arange(10.))]:
290+
self.assertRaises(TypeError, lambda : infer_freq(s))
291+
292+
# a non-convertible string
293+
self.assertRaises(ValueError, lambda : infer_freq(Series(['foo','bar'])))
294+
295+
# cannot infer on PeriodIndex
296+
for freq in [None, 'MS', 'Y']:
297+
s = Series(period_range('2013',periods=10,freq=freq))
298+
self.assertRaises(TypeError, lambda : infer_freq(s))
299+
300+
# DateTimeIndex
301+
for freq in ['MS', 'L', 'S']:
302+
s = Series(date_range('20130101',periods=10,freq=freq))
303+
inferred = infer_freq(s)
304+
self.assertEqual(inferred,freq)
305+
306+
s = Series(date_range('20130101','20130110'))
307+
inferred = infer_freq(s)
308+
self.assertEqual(inferred,'D')
309+
272310
MONTHS = ['JAN', 'FEB', 'MAR', 'APR', 'MAY', 'JUN', 'JUL', 'AUG', 'SEP',
273311
'OCT', 'NOV', 'DEC']
274312

0 commit comments

Comments
 (0)