Skip to content

Commit 9e440c8

Browse files
committed
ENH: Allow conversion of datetime64 and timedelta64 to string in astype (GH 9757)
1 parent 9e4e447 commit 9e440c8

File tree

4 files changed

+47
-6
lines changed

4 files changed

+47
-6
lines changed

doc/source/whatsnew/v0.16.1.txt

+1
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ Enhancements
3030
df = DataFrame(np.random.randn(3, 3), columns=['A', 'B', 'C'])
3131
df.drop(['A', 'X'], axis=1, errors='ignore')
3232

33+
- Allow conversion of values with dtype ``datetime64`` or ``timedelta64`` to strings using ``astype(str)`` (:issue:`9757`)
3334

3435
.. _whatsnew_0161.api:
3536

pandas/core/common.py

+6-6
Original file line numberDiff line numberDiff line change
@@ -2637,7 +2637,12 @@ def _astype_nansafe(arr, dtype, copy=True):
26372637
if not isinstance(dtype, np.dtype):
26382638
dtype = _coerce_to_dtype(dtype)
26392639

2640-
if is_datetime64_dtype(arr):
2640+
if issubclass(dtype.type, compat.text_type):
2641+
# in Py3 that's str, in Py2 that's unicode
2642+
return lib.astype_unicode(arr.ravel()).reshape(arr.shape)
2643+
elif issubclass(dtype.type, compat.string_types):
2644+
return lib.astype_str(arr.ravel()).reshape(arr.shape)
2645+
elif is_datetime64_dtype(arr):
26412646
if dtype == object:
26422647
return tslib.ints_to_pydatetime(arr.view(np.int64))
26432648
elif dtype == np.int64:
@@ -2675,11 +2680,6 @@ def _astype_nansafe(arr, dtype, copy=True):
26752680
elif arr.dtype == np.object_ and np.issubdtype(dtype.type, np.integer):
26762681
# work around NumPy brokenness, #1987
26772682
return lib.astype_intsafe(arr.ravel(), dtype).reshape(arr.shape)
2678-
elif issubclass(dtype.type, compat.text_type):
2679-
# in Py3 that's str, in Py2 that's unicode
2680-
return lib.astype_unicode(arr.ravel()).reshape(arr.shape)
2681-
elif issubclass(dtype.type, compat.string_types):
2682-
return lib.astype_str(arr.ravel()).reshape(arr.shape)
26832683

26842684
if copy:
26852685
return arr.astype(dtype)

pandas/tests/test_frame.py

+27
Original file line numberDiff line numberDiff line change
@@ -4192,6 +4192,33 @@ def test_astype_cast_nan_int(self):
41924192
df = DataFrame(data={"Values": [1.0, 2.0, 3.0, np.nan]})
41934193
self.assertRaises(ValueError, df.astype, np.int64)
41944194

4195+
def test_astype_str(self):
4196+
# GH9757
4197+
dts = Series(date_range('2010-01-04', periods=5))
4198+
tds = Series([Timedelta(x, unit='d') for x in range(5)])
4199+
ns = Series(range(5))
4200+
fs = Series([0.0, 0.2, 0.4, 0.6, 0.8])
4201+
4202+
df = pd.DataFrame({
4203+
'dts' : dts,
4204+
'tds' : tds,
4205+
'ns' : ns,
4206+
'fs' : fs,
4207+
})
4208+
4209+
# Test str and unicode on python 2.x and just str on python 3.x
4210+
for tt in set([str, compat.text_type]):
4211+
result = df.astype(tt)
4212+
4213+
expected = pd.DataFrame({
4214+
'dts' : list(map(tt, dts.values)),
4215+
'tds' : list(map(tt, tds.values)),
4216+
'ns' : list(map(tt, ns.values)),
4217+
'fs' : list(map(tt, fs.values)),
4218+
})
4219+
4220+
assert_frame_equal(result, expected)
4221+
41954222
def test_array_interface(self):
41964223
result = np.sqrt(self.frame)
41974224
tm.assert_isinstance(result, type(self.frame))

pandas/tests/test_series.py

+13
Original file line numberDiff line numberDiff line change
@@ -5511,6 +5511,19 @@ def test_astype_str(self):
55115511
expec = s.map(compat.text_type)
55125512
assert_series_equal(res, expec)
55135513

5514+
# GH9757
5515+
# Test str and unicode on python 2.x and just str on python 3.x
5516+
for tt in set([str, compat.text_type]):
5517+
ts = Series([Timestamp('2010-01-04 00:00:00')])
5518+
s = ts.astype(tt)
5519+
expected = Series([tt(ts.values[0])])
5520+
assert_series_equal(s, expected)
5521+
5522+
td = Series([Timedelta(1, unit='d')])
5523+
s = td.astype(tt)
5524+
expected = Series([tt(td.values[0])])
5525+
assert_series_equal(s, expected)
5526+
55145527
def test_astype_unicode(self):
55155528

55165529
# GH7758

0 commit comments

Comments
 (0)