Skip to content

API: validate conversions of datetimeindex with tz, and fixup to_series() to handle (GH6032) #6398

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: 1 addition & 1 deletion doc/source/api.rst
Original file line number Diff line number Diff line change
Expand Up @@ -1176,7 +1176,7 @@ Conversion
DatetimeIndex.to_datetime
DatetimeIndex.to_period
DatetimeIndex.to_pydatetime

DatetimeIndex.to_series

GroupBy
-------
Expand Down
2 changes: 2 additions & 0 deletions pandas/core/frame.py
Original file line number Diff line number Diff line change
Expand Up @@ -2033,6 +2033,8 @@ def _sanitize_column(self, key, value):
value = com._asarray_tuplesafe(value)
elif isinstance(value, PeriodIndex):
value = value.asobject
elif isinstance(value, DatetimeIndex):
value = value._to_embed(keep_tz=True).copy()
elif value.ndim == 2:
value = value.copy().T
else:
Expand Down
21 changes: 18 additions & 3 deletions pandas/core/index.py
Original file line number Diff line number Diff line change
Expand Up @@ -266,13 +266,28 @@ def copy(self, names=None, name=None, dtype=None, deep=False):
new_index = new_index.astype(dtype)
return new_index

def to_series(self):
def to_series(self, keep_tz=False):
"""
return a series with both index and values equal to the index keys
Create a Series with both index and values equal to the index keys
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

To follow the numpy docstring standard, there should be a short explanation (followed by a blank line) above the parameters section.

useful with map for returning an indexer based on an index
Parameters
----------
keep_tz : optional, defaults False.
applies only to a DatetimeIndex
Returns
-------
Series : dtype will be based on the type of the Index values.
"""

import pandas as pd
return pd.Series(self.values, index=self, name=self.name)
values = self._to_embed(keep_tz)
return pd.Series(values, index=self, name=self.name)

def _to_embed(self, keep_tz=False):
""" return an array repr of this object, potentially casting to object """
return self.values

def astype(self, dtype):
return Index(self.values.astype(dtype), name=self.name,
Expand Down
3 changes: 2 additions & 1 deletion pandas/core/series.py
Original file line number Diff line number Diff line change
Expand Up @@ -162,7 +162,8 @@ def __init__(self, data=None, index=None, dtype=None, name=None,
# need to copy to avoid aliasing issues
if name is None:
name = data.name
data = data.values

data = data._to_embed(keep_tz=True)
copy = True
elif isinstance(data, pa.Array):
pass
Expand Down
27 changes: 27 additions & 0 deletions pandas/tests/test_frame.py
Original file line number Diff line number Diff line change
Expand Up @@ -2092,6 +2092,33 @@ def test_set_index_cast_datetimeindex(self):
idf = df.set_index('A')
tm.assert_isinstance(idf.index, DatetimeIndex)

# don't cast a DatetimeIndex WITH a tz, leave as object
# GH 6032
i = pd.DatetimeIndex(pd.tseries.tools.to_datetime(['2013-1-1 13:00','2013-1-2 14:00'], errors="raise")).tz_localize('US/Pacific')
df = DataFrame(np.random.randn(2,1),columns=['A'])

expected = Series(i)
self.assertTrue(expected.dtype == object)
self.assertTrue(i.equals(expected.values.values))

df['B'] = i
result = df['B']
assert_series_equal(result, expected)

result = i.to_series(keep_tz=True)
assert_series_equal(result.reset_index(drop=True), expected)

df['C'] = i.to_series().reset_index(drop=True)
result = df['C']
comp = DatetimeIndex(expected.values).copy()
comp.tz = None
self.assert_numpy_array_equal(result.values, comp.values)

# list of datetimes with a tz
df['D'] = i.to_pydatetime()
result = df['D']
assert_series_equal(result, expected)

def test_set_index_multiindexcolumns(self):
columns = MultiIndex.from_tuples([('foo', 1), ('foo', 2), ('bar', 1)])
df = DataFrame(np.random.randn(3, 3), columns=columns)
Expand Down
32 changes: 32 additions & 0 deletions pandas/tseries/index.py
Original file line number Diff line number Diff line change
Expand Up @@ -721,6 +721,38 @@ def _get_time_micros(self):
values = self._local_timestamps()
return tslib.get_time_micros(values)

def to_series(self, keep_tz=False):
"""
Create a Series with both index and values equal to the index keys
useful with map for returning an indexer based on an index
Parameters
----------
keep_tz : optional, defaults False.
return the data keeping the timezone.
If keep_tz is True:
If the timezone is not set or is UTC, the resulting
Series will have a datetime64[ns] dtype.
Otherwise the Series will have an object dtype.
If keep_tz is False:
Series will have a datetime64[ns] dtype.
Returns
-------
Series
"""
return super(DatetimeIndex, self).to_series(keep_tz=keep_tz)

def _to_embed(self, keep_tz=False):
""" return an array repr of this object, potentially casting to object """
if keep_tz and self.tz is not None and str(self.tz) != 'UTC':
return self.asobject
return self.values

@property
def asobject(self):
"""
Expand Down