Repository: pandas-dev/pandas

Issue:
pd.to_timedelta(single_string) returns a Series, which ruins broadcasting.
Currently

```
In [10]: pd.to_timedelta(Series(['00:03:37', '00:05:05'])) - pd.to_timedelta('00:03:00')
Out[10]: 
0   00:00:37
1        NaT
dtype: timedelta64[ns]
```

because

```
In [13]: pd.to_timedelta('00:03:00')
Out[13]: 
0   00:03:00
dtype: timedelta64[ns]
```

More expected and consistent behavior, in my opinion, would be

```
In [12]: pd.to_timedelta(Series(['00:03:37', '00:05:05'])) - pd.to_timedelta('00:03:00')
Out[12]: 
0   00:00:37
1   00:02:05
dtype: timedelta64[ns]
```

If, instead, `pd.to_timedelta('00:03:00')` gave `numpy.timedelta64(180000000000,'ns')`, it would broadcast properly, as demonstrated by this work-around

```
In [12]: pd.to_timedelta(Series(['00:03:37', '00:05:05'])) - pd.to_timedelta('00:03:00')[0]
Out[12]: 
0   00:00:37
1   00:02:05
dtype: timedelta64[ns]
```

I have not regularly used timedeltas until now. Am I misjudging the expected usage?

**Update**, OK, one can also get the expected result by setting `box=False`. But `box=False` should be default for a scalar, no?



Discussion:
this is correct (and on purpose); we don't have a timedelta scalar ATM (like Timestamp), so only option is to return a timedelta64, which works but is not friendly 

Understood.

this particular usage is easy to fix though (this is a_bug_ I guess in the timedelta subtraction) operation....marking for 0.14

So, until Timedelta scalars come along, worth submitting a PR that returns timedelta64 when input is not list-like?

or...could just have a single element `pd.to_timedelta(...)` return the underlying value...

Yeah, I think we are saying the same thing. I'll make a PR.

you can try it and see what breaks...it _should_ work (I think)....and I think that is right actually...(to return a single-element as a timedelta64, bascially just don't box it), `to_datetime` DOES return a Timestamp for a single element


Resolving patch:
diff --git a/pandas/tseries/timedeltas.py b/pandas/tseries/timedeltas.py
--- a/pandas/tseries/timedeltas.py
+++ b/pandas/tseries/timedeltas.py
@@ -58,7 +58,8 @@ def _convert_listlike(arg, box):
     elif is_list_like(arg):
         return _convert_listlike(arg, box=box)
 
-    return _convert_listlike([ arg ], box=box)
+    # ...so it must be a scalar value. Return scalar.
+    return _coerce_scalar_to_timedelta_type(arg, unit=unit)
 
 _short_search = re.compile(
     "^\s*(?P<neg>-?)\s*(?P<value>\d*\.?\d*)\s*(?P<unit>d|s|ms|us|ns)?\s*$",re.IGNORECASE)


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
@@ -2314,6 +2314,25 @@ def test_timedelta64_operations_with_timedeltas(self):
         # roundtrip
         assert_series_equal(result + td2,td1)
 
+        # Now again, using pd.to_timedelta, which should build
+        # a Series or a scalar, depending on input.
+        if not _np_version_under1p7:
+            td1 = Series(pd.to_timedelta(['00:05:03'] * 3))
+            td2 = pd.to_timedelta('00:05:04')
+            result = td1 - td2
+            expected = Series([timedelta(seconds=0)] * 3) -Series(
+                [timedelta(seconds=1)] * 3)
+            self.assert_(result.dtype == 'm8[ns]')
+            assert_series_equal(result, expected)
+
+            result2 = td2 - td1
+            expected = (Series([timedelta(seconds=1)] * 3) -
+                        Series([timedelta(seconds=0)] * 3))
+            assert_series_equal(result2, expected)
+
+            # roundtrip
+            assert_series_equal(result + td2,td1)
+
     def test_timedelta64_operations_with_integers(self):
 
         # GH 4521
diff --git a/pandas/tseries/tests/test_timedeltas.py b/pandas/tseries/tests/test_timedeltas.py
--- a/pandas/tseries/tests/test_timedeltas.py
+++ b/pandas/tseries/tests/test_timedeltas.py
@@ -180,17 +180,20 @@ def test_timedelta_ops(self):
         s = Series([Timestamp('20130101') + timedelta(seconds=i*i) for i in range(10) ])
         td = s.diff()
 
-        result = td.mean()
+        result = td.mean()[0]
+        # TODO This should have returned a scalar to begin with. Hack for now.
         expected = to_timedelta(timedelta(seconds=9))
-        tm.assert_series_equal(result, expected)
+        tm.assert_almost_equal(result, expected)
 
         result = td.quantile(.1)
+        # This properly returned a scalar.
         expected = to_timedelta('00:00:02.6')
-        tm.assert_series_equal(result, expected)
+        tm.assert_almost_equal(result, expected)
 
-        result = td.median()
+        result = td.median()[0]
+        # TODO This should have returned a scalar to begin with. Hack for now.
         expected = to_timedelta('00:00:08')
-        tm.assert_series_equal(result, expected)
+        tm.assert_almost_equal(result, expected)
 
 if __name__ == '__main__':
     nose.runmodule(argv=[__file__, '-vvs', '-x', '--pdb', '--pdb-failure'],