Skip to content

Commit 4ea4cfc

Browse files
Chang Shewesm
Chang She
authored andcommitted
ENH: maybe upcast masked arrays passed to DataFrame constructor
1 parent 714b28c commit 4ea4cfc

File tree

2 files changed

+72
-1
lines changed

2 files changed

+72
-1
lines changed

pandas/core/frame.py

+5-1
Original file line numberDiff line numberDiff line change
@@ -304,7 +304,11 @@ def __init__(self, data=None, index=None, columns=None, dtype=None,
304304
elif isinstance(data, ma.MaskedArray):
305305
mask = ma.getmaskarray(data)
306306
datacopy = ma.copy(data)
307-
datacopy[mask] = np.nan
307+
if issubclass(data.dtype.type, np.datetime64):
308+
datacopy[mask] = lib.NaT
309+
else:
310+
datacopy = com._maybe_upcast(datacopy)
311+
datacopy[mask] = np.nan
308312
mgr = self._init_ndarray(datacopy, index, columns, dtype=dtype,
309313
copy=copy)
310314
elif isinstance(data, np.ndarray):

pandas/tests/test_frame.py

+67
Original file line numberDiff line numberDiff line change
@@ -1601,6 +1601,73 @@ def test_constructor_maskedarray(self):
16011601
frame = DataFrame(ma.masked_all((3, 0)))
16021602
self.assert_(len(frame.columns) == 0)
16031603

1604+
def test_constructor_maskedarray_nonfloat(self):
1605+
# masked int promoted to float
1606+
mat = ma.masked_all((2, 3), dtype=int)
1607+
# 2-D input
1608+
frame = DataFrame(mat, columns=['A', 'B', 'C'], index=[1, 2])
1609+
1610+
self.assertEqual(len(frame.index), 2)
1611+
self.assertEqual(len(frame.columns), 3)
1612+
self.assertTrue(np.all(~np.asarray(frame == frame)))
1613+
1614+
# cast type
1615+
frame = DataFrame(mat, columns=['A', 'B', 'C'],
1616+
index=[1, 2], dtype=float)
1617+
self.assert_(frame.values.dtype == np.float64)
1618+
1619+
# Check non-masked values
1620+
mat2 = ma.copy(mat)
1621+
mat2[0,0] = 1
1622+
mat2[1,2] = 2
1623+
frame = DataFrame(mat2, columns=['A', 'B', 'C'], index=[1, 2])
1624+
self.assertEqual(1, frame['A'][1])
1625+
self.assertEqual(2, frame['C'][2])
1626+
1627+
# masked np.datetime64 stays (use lib.NaT as null)
1628+
mat = ma.masked_all((2, 3), dtype=np.datetime64)
1629+
# 2-D input
1630+
frame = DataFrame(mat, columns=['A', 'B', 'C'], index=[1, 2])
1631+
1632+
self.assertEqual(len(frame.index), 2)
1633+
self.assertEqual(len(frame.columns), 3)
1634+
self.assertTrue(isnull(frame).values.all())
1635+
1636+
# cast type
1637+
frame = DataFrame(mat, columns=['A', 'B', 'C'],
1638+
index=[1, 2], dtype=int)
1639+
self.assert_(frame.values.dtype == int)
1640+
1641+
# Check non-masked values
1642+
mat2 = ma.copy(mat)
1643+
mat2[0,0] = 1
1644+
mat2[1,2] = 2
1645+
frame = DataFrame(mat2, columns=['A', 'B', 'C'], index=[1, 2])
1646+
self.assertEqual(1, frame['A'].view('i8')[1])
1647+
self.assertEqual(2, frame['C'].view('i8')[2])
1648+
1649+
# masked bool promoted to object
1650+
mat = ma.masked_all((2, 3), dtype=bool)
1651+
# 2-D input
1652+
frame = DataFrame(mat, columns=['A', 'B', 'C'], index=[1, 2])
1653+
1654+
self.assertEqual(len(frame.index), 2)
1655+
self.assertEqual(len(frame.columns), 3)
1656+
self.assertTrue(np.all(~np.asarray(frame == frame)))
1657+
1658+
# cast type
1659+
frame = DataFrame(mat, columns=['A', 'B', 'C'],
1660+
index=[1, 2], dtype=object)
1661+
self.assert_(frame.values.dtype == object)
1662+
1663+
# Check non-masked values
1664+
mat2 = ma.copy(mat)
1665+
mat2[0,0] = True
1666+
mat2[1,2] = False
1667+
frame = DataFrame(mat2, columns=['A', 'B', 'C'], index=[1, 2])
1668+
self.assertEqual(True, frame['A'][1])
1669+
self.assertEqual(False, frame['C'][2])
1670+
16041671
def test_constructor_corner(self):
16051672
df = DataFrame(index=[])
16061673
self.assertEqual(df.values.shape, (0, 0))

0 commit comments

Comments
 (0)