Skip to content

API: pd.infer_freq interacts correctly with a Series #6408

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Feb 19, 2014
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions doc/source/release.rst
Original file line number Diff line number Diff line change
Expand Up @@ -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
~~~~~~~~~~~~~~~~~~~~~
Expand Down
1 change: 1 addition & 0 deletions doc/source/v0.14.0.txt
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ API changes
- ``week,dayofweek,dayofyear,quarter``
- ``microsecond,nanosecond,qyear``
- ``min(),max()``
- ``pd.infer_freq()``

.. ipython:: python

Expand Down
25 changes: 15 additions & 10 deletions pandas/tseries/frequencies.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@
import pandas.lib as lib
import pandas.tslib as tslib


class FreqGroup(object):
FR_ANN = 1000
FR_QTR = 2000
Expand Down Expand Up @@ -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()

Expand Down
44 changes: 41 additions & 3 deletions pandas/tseries/tests/test_frequencies.py
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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'
Expand Down Expand Up @@ -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'])
Expand Down Expand Up @@ -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']

Expand Down