Skip to content

Commit f2a7b9c

Browse files
committed
Merge pull request #4641 from jreback/arthops
ENH: (GH4629) Support for using a DatetimeIndex/PeriodsIndex directly in a datelike calculation
2 parents 209e248 + 0990a75 commit f2a7b9c

File tree

3 files changed

+34
-4
lines changed

3 files changed

+34
-4
lines changed

doc/source/release.rst

+2
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,8 @@ pandas 0.13
6161
is frequency conversion.
6262
- Performance improvements with ``__getitem__`` on ``DataFrames`` with
6363
when the key is a column
64+
- Support for using a ``DatetimeIndex/PeriodsIndex`` directly in a datelike calculation
65+
e.g. s-s.index (:issue:`4629`)
6466

6567
**API Changes**
6668

pandas/core/series.py

+8-4
Original file line numberDiff line numberDiff line change
@@ -103,14 +103,16 @@ def wrapper(self, other, name=name):
103103
coerce = 'compat' if _np_version_under1p7 else True
104104

105105
# convert the argument to an ndarray
106-
def convert_to_array(values):
106+
def convert_to_array(values, other=None):
107107
if not is_list_like(values):
108108
values = np.array([values])
109109
inferred_type = lib.infer_dtype(values)
110110
if inferred_type in set(['datetime64','datetime','date','time']):
111111
# a datetlike
112112
if not (isinstance(values, (pa.Array, Series)) and com.is_datetime64_dtype(values)):
113113
values = tslib.array_to_datetime(values)
114+
elif isinstance(values, DatetimeIndex):
115+
other = values = values.to_series()
114116
elif inferred_type in set(['timedelta']):
115117
# have a timedelta, convert to to ns here
116118
values = com._possibly_cast_to_timedelta(values, coerce=coerce)
@@ -121,6 +123,8 @@ def convert_to_array(values):
121123
# py3 compat where dtype is 'm' but is an integer
122124
if values.dtype.kind == 'm':
123125
values = values.astype('timedelta64[ns]')
126+
elif isinstance(values, PeriodIndex):
127+
other = values = values.to_timestamp().to_series()
124128
elif name not in ['__truediv__','__div__','__mul__']:
125129
raise TypeError("incompatible type for a datetime/timedelta operation [{0}]".format(name))
126130
elif isinstance(values[0],DateOffset):
@@ -134,11 +138,11 @@ def convert_to_array(values):
134138
else:
135139
raise TypeError("incompatible type [{0}] for a datetime/timedelta operation".format(pa.array(values).dtype))
136140

137-
return values
141+
return values, other
138142

139143
# convert lhs and rhs
140-
lvalues = convert_to_array(lvalues)
141-
rvalues = convert_to_array(rvalues)
144+
lvalues,_ = convert_to_array(lvalues)
145+
rvalues,other = convert_to_array(rvalues,other)
142146

143147
is_datetime_rhs = com.is_datetime64_dtype(rvalues)
144148
is_timedelta_rhs = com.is_timedelta64_dtype(rvalues) or (not is_datetime_rhs and _np_version_under1p7)

pandas/tests/test_series.py

+24
Original file line numberDiff line numberDiff line change
@@ -2326,6 +2326,30 @@ def test_sub_of_datetime_from_TimeSeries(self):
23262326
result = com._possibly_cast_to_timedelta(np.abs(a - b))
23272327
self.assert_(result.dtype == 'timedelta64[ns]')
23282328

2329+
def test_datetime64_with_index(self):
2330+
2331+
# arithmetic integer ops with an index
2332+
s = Series(np.random.randn(5))
2333+
expected = s-s.index.to_series()
2334+
result = s-s.index
2335+
assert_series_equal(result,expected)
2336+
2337+
# GH 4629
2338+
# arithmetic datetime64 ops with an index
2339+
s = Series(date_range('20130101',periods=5),index=date_range('20130101',periods=5))
2340+
expected = s-s.index.to_series()
2341+
result = s-s.index
2342+
assert_series_equal(result,expected)
2343+
2344+
result = s-s.index.to_period()
2345+
assert_series_equal(result,expected)
2346+
2347+
df = DataFrame(np.random.randn(5,2),index=date_range('20130101',periods=5))
2348+
df['date'] = Timestamp('20130102')
2349+
df['expected'] = df['date']-df.index.to_series()
2350+
df['result'] = df['date']-df.index
2351+
assert_series_equal(df['result'],df['expected'])
2352+
23292353
def test_timedelta64_nan(self):
23302354

23312355
from pandas import tslib

0 commit comments

Comments
 (0)