Repository: pandas-dev/pandas

Issue:
API: arithmetic ops could accept an index as appropriate
Not sure if this will cause weirdness but haveing the arithmetic operations able to accept an index (when appropriate type), e.g. a datecolumn should be able to interact with a DatetimeIndex, but prob should prohibit an int column from interacting with a IntIndex?

e.g. in below `df['date']-df.index` should work

This actually DOES work now! (and I take it back, does make some sense)
should `df[1]-df.reset_index().index` work????

http://stackoverflow.com/questions/18368442/how-to-directly-use-pandas-date-time-index-in-calculations/18368793?noredirect=1#comment26971689_18368793

```
In [1]: df = DataFrame(randn(5,2),index=date_range('20130101',periods=5))

In [3]: df['date'] = Timestamp('20130102')

In [4]: df
Out[4]: 
                   0         1                date
2013-01-01  2.406932 -0.313473 2013-01-02 00:00:00
2013-01-02  0.034162 -0.708450 2013-01-02 00:00:00
2013-01-03 -1.585031  0.587243 2013-01-02 00:00:00
2013-01-04  1.454818  1.089208 2013-01-02 00:00:00
2013-01-05 -0.778016 -0.994242 2013-01-02 00:00:00

In [5]: df['td'] = df['date']-df.index.to_series()

In [6]: df
Out[6]: 
                   0         1                date                td
2013-01-01  2.406932 -0.313473 2013-01-02 00:00:00  1 days, 00:00:00
2013-01-02  0.034162 -0.708450 2013-01-02 00:00:00          00:00:00
2013-01-03 -1.585031  0.587243 2013-01-02 00:00:00 -1 days, 00:00:00
2013-01-04  1.454818  1.089208 2013-01-02 00:00:00 -2 days, 00:00:00
2013-01-05 -0.778016 -0.994242 2013-01-02 00:00:00 -3 days, 00:00:00
```



Discussion:
@jreback why would you expect this not to work? `Index` is just an ndarray with some ops disabled.  It won't work with a MultiIndex and I don't think there's a clear reason to make that work.

@jtratner no i expect it TO work

I guess there is some setting going on, so need to just fix it (e.g. just do index.to_series) is prob enough
I think only matters for DatetimeIndex (as it hits that special loop)

```
In [16]: df['date']-df.index
---------------------------------------------------------------------------
AttributeError                            Traceback (most recent call last)
<ipython-input-16-bdf30f864601> in <module>()
----> 1 df['date']-x

/usr/local/lib/python2.7/site-packages/pandas-0.12.0-py2.7-linux-x86_64.egg/pandas/core/series.pyc in wrapper(self, other, name)
    154 
    155             lvalues = lvalues.view('i8')
--> 156             rvalues = rvalues.view('i8')
    157 
    158         if isinstance(rvalues, Series):

AttributeError: can't set attribute
```

@jreback fun, no traceback either?

yep..just bad error message....think need to add a check if the lvalues/rvalues are an Index, :( sigh

@jreback are you sure this isn't something wrong with the way `Index` is currently defined (e.g., something overriding `view()`, like an aliasing to copy that then thinks that it's the first positional argument tot the function and tries to set it)?


Resolving patch:
diff --git a/pandas/core/series.py b/pandas/core/series.py
--- a/pandas/core/series.py
+++ b/pandas/core/series.py
@@ -103,7 +103,7 @@ def wrapper(self, other, name=name):
             coerce = 'compat' if _np_version_under1p7 else True
 
             # convert the argument to an ndarray
-            def convert_to_array(values):
+            def convert_to_array(values, other=None):
                 if not is_list_like(values):
                     values = np.array([values])
                 inferred_type = lib.infer_dtype(values)
@@ -111,6 +111,8 @@ def convert_to_array(values):
                     # a datetlike
                     if not (isinstance(values, (pa.Array, Series)) and com.is_datetime64_dtype(values)):
                         values = tslib.array_to_datetime(values)
+                    elif isinstance(values, DatetimeIndex):
+                        other = values = values.to_series()
                 elif inferred_type in set(['timedelta']):
                     # have a timedelta, convert to to ns here
                     values = com._possibly_cast_to_timedelta(values, coerce=coerce)
@@ -121,6 +123,8 @@ def convert_to_array(values):
                     # py3 compat where dtype is 'm' but is an integer
                     if values.dtype.kind == 'm':
                         values = values.astype('timedelta64[ns]')
+                    elif isinstance(values, PeriodIndex):
+                        other = values = values.to_timestamp().to_series()
                     elif name not in ['__truediv__','__div__','__mul__']:
                         raise TypeError("incompatible type for a datetime/timedelta operation [{0}]".format(name))
                 elif isinstance(values[0],DateOffset):
@@ -134,11 +138,11 @@ def convert_to_array(values):
                 else:
                     raise TypeError("incompatible type [{0}] for a datetime/timedelta operation".format(pa.array(values).dtype))
 
-                return values
+                return values, other
 
             # convert lhs and rhs
-            lvalues = convert_to_array(lvalues)
-            rvalues = convert_to_array(rvalues)
+            lvalues,_ = convert_to_array(lvalues)
+            rvalues,other = convert_to_array(rvalues,other)
 
             is_datetime_rhs  = com.is_datetime64_dtype(rvalues)
             is_timedelta_rhs = com.is_timedelta64_dtype(rvalues) or (not is_datetime_rhs and _np_version_under1p7)


Test patch:
diff --git a/pandas/tests/test_series.py b/pandas/tests/test_series.py
--- a/pandas/tests/test_series.py
+++ b/pandas/tests/test_series.py
@@ -2319,6 +2319,30 @@ def test_sub_of_datetime_from_TimeSeries(self):
         result = com._possibly_cast_to_timedelta(np.abs(a - b))
         self.assert_(result.dtype == 'timedelta64[ns]')
 
+    def test_datetime64_with_index(self):
+
+        # arithmetic integer ops with an index
+        s = Series(np.random.randn(5))
+        expected = s-s.index.to_series()
+        result = s-s.index
+        assert_series_equal(result,expected)
+
+        # GH 4629
+        # arithmetic datetime64 ops with an index
+        s = Series(date_range('20130101',periods=5),index=date_range('20130101',periods=5))
+        expected = s-s.index.to_series()
+        result = s-s.index
+        assert_series_equal(result,expected)
+
+        result = s-s.index.to_period()
+        assert_series_equal(result,expected)
+
+        df = DataFrame(np.random.randn(5,2),index=date_range('20130101',periods=5))
+        df['date'] = Timestamp('20130102')
+        df['expected'] = df['date']-df.index.to_series()
+        df['result'] = df['date']-df.index
+        assert_series_equal(df['result'],df['expected'])
+
     def test_timedelta64_nan(self):
 
         from pandas import tslib