Skip to content

Commit 6fe19fd

Browse files
committed
Merge pull request #2958 from jreback/timedelta_2957_new
BUG: fixed .abs on Series with a timedelta (partial fix for 2957)
2 parents e108107 + bd7750a commit 6fe19fd

File tree

5 files changed

+40
-9
lines changed

5 files changed

+40
-9
lines changed

RELEASE.rst

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -122,7 +122,7 @@ pandas 0.11.0
122122
- Support null checking on timedelta64, representing (and formatting) with NaT
123123
- Support setitem with np.nan value, converts to NaT
124124
- Support min/max ops in a Dataframe (abs not working, nor do we error on non-supported ops)
125-
- Support idxmin/idxmax in a Series (but with no NaT)
125+
- Support idxmin/idxmax/abs in a Series (but with no NaT)
126126

127127
- Bug on in-place putmasking on an ``integer`` series that needs to be converted to ``float`` (GH2746_)
128128
- Bug in argsort of ``datetime64[ns]`` Series with ``NaT`` (GH2967_)

pandas/core/common.py

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -916,7 +916,7 @@ def _possibly_convert_platform(values):
916916
return values
917917

918918

919-
def _possibly_cast_to_timedelta(value):
919+
def _possibly_cast_to_timedelta(value, coerce=True):
920920
""" try to cast to timedelta64 w/o coercion """
921921

922922
# deal with numpy not being able to handle certain timedelta operations
@@ -925,9 +925,12 @@ def _possibly_cast_to_timedelta(value):
925925
value = value.astype('timedelta64[ns]')
926926
return value
927927

928-
new_value = tslib.array_to_timedelta64(value.astype(object), coerce=False)
929-
if new_value.dtype == 'i8':
930-
value = np.array(new_value,dtype='timedelta64[ns]')
928+
# we don't have a timedelta, but we want to try to convert to one (but don't force it)
929+
if coerce:
930+
new_value = tslib.array_to_timedelta64(value.astype(object), coerce=False)
931+
if new_value.dtype == 'i8':
932+
value = np.array(new_value,dtype='timedelta64[ns]')
933+
931934
return value
932935

933936
def _possibly_cast_to_datetime(value, dtype, coerce = False):

pandas/core/series.py

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -711,6 +711,19 @@ def mask(self, cond):
711711
"""
712712
return self.where(~cond, nan)
713713

714+
def abs(self):
715+
"""
716+
Return an object with absolute value taken. Only applicable to objects
717+
that are all numeric
718+
719+
Returns
720+
-------
721+
abs: type of caller
722+
"""
723+
obj = np.abs(self)
724+
obj = com._possibly_cast_to_timedelta(obj, coerce=False)
725+
return obj
726+
714727
def __setitem__(self, key, value):
715728
try:
716729
try:

pandas/tests/test_frame.py

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2913,10 +2913,11 @@ def test_operators_timedelta64(self):
29132913
self.assert_((result == diffs['A']).all() == True)
29142914

29152915
# abs ###### THIS IS BROKEN NOW ###### (results are dtype=timedelta64[us]
2916-
result = np.abs(df['A']-df['B'])
2917-
result = diffs.abs()
2918-
expected = DataFrame(dict(A = df['A']-df['C'],
2919-
B = df['B']-df['A']))
2916+
# even though fixed in series
2917+
#result = np.abs(df['A']-df['B'])
2918+
#result = diffs.abs()
2919+
#expected = DataFrame(dict(A = df['A']-df['C'],
2920+
# B = df['B']-df['A']))
29202921
#assert_frame_equal(result,expected)
29212922

29222923
# mixed frame

pandas/tests/test_series.py

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1801,9 +1801,11 @@ def test_operators_timedelta64(self):
18011801
self.assert_(result.dtype=='m8[ns]')
18021802
assert_series_equal(result,expected)
18031803

1804+
18041805
def test_timedelta64_functions(self):
18051806

18061807
from datetime import timedelta
1808+
from pandas import date_range
18071809

18081810
# index min/max
18091811
td = Series(date_range('2012-1-1', periods=3, freq='D'))-Timestamp('20120101')
@@ -1823,6 +1825,18 @@ def test_timedelta64_functions(self):
18231825
#result = td.idxmax()
18241826
#self.assert_(result == 2)
18251827

1828+
# abs
1829+
s1 = Series(date_range('20120101',periods=3))
1830+
s2 = Series(date_range('20120102',periods=3))
1831+
expected = Series(s2-s1)
1832+
1833+
# this fails as numpy returns timedelta64[us]
1834+
#result = np.abs(s1-s2)
1835+
#assert_frame_equal(result,expected)
1836+
1837+
result = (s1-s2).abs()
1838+
assert_series_equal(result,expected)
1839+
18261840
def test_sub_of_datetime_from_TimeSeries(self):
18271841
from pandas.core import common as com
18281842
from datetime import datetime

0 commit comments

Comments
 (0)