Skip to content

Commit 3ce416b

Browse files
committed
BUG: avoid unnecessary copies when passed dtype matches DataFrame/ndarray in DataFrame constructor close #1572
1 parent 9a8ad65 commit 3ce416b

File tree

3 files changed

+27
-6
lines changed

3 files changed

+27
-6
lines changed

pandas/core/frame.py

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -434,8 +434,9 @@ def _init_mgr(self, mgr, index, columns, dtype=None, copy=False):
434434
if copy and dtype is None:
435435
mgr = mgr.copy()
436436
elif dtype is not None:
437-
# no choice but to copy
438-
mgr = mgr.astype(dtype)
437+
# avoid copy if we can
438+
if len(mgr.blocks) > 1 or mgr.blocks[0].values.dtype != dtype:
439+
mgr = mgr.astype(dtype)
439440
return mgr
440441

441442
def _init_dict(self, data, index, columns, dtype=None):
@@ -482,10 +483,11 @@ def _init_ndarray(self, values, index, columns, dtype=None,
482483
values = _prep_ndarray(values, copy=copy)
483484

484485
if dtype is not None:
485-
try:
486-
values = values.astype(dtype)
487-
except Exception:
488-
raise ValueError('failed to cast to %s' % dtype)
486+
if values.dtype != dtype:
487+
try:
488+
values = values.astype(dtype)
489+
except Exception:
490+
raise ValueError('failed to cast to %s' % dtype)
489491

490492
N, K = values.shape
491493

pandas/tests/test_frame.py

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1468,6 +1468,16 @@ def test_constructor_cast_failure(self):
14681468
foo = DataFrame({'a': ['a', 'b', 'c']}, dtype=np.float64)
14691469
self.assert_(foo['a'].dtype == object)
14701470

1471+
def test_constructor_dtype_nocast_view(self):
1472+
df = DataFrame([[1, 2]])
1473+
should_be_view = DataFrame(df, dtype=df[0].dtype)
1474+
should_be_view[0][0] = 99
1475+
self.assertEqual(df.values[0, 0], 99)
1476+
1477+
should_be_view = DataFrame(df.values, dtype=df[0].dtype)
1478+
should_be_view[0][0] = 97
1479+
self.assertEqual(df.values[0, 0], 97)
1480+
14711481
def test_constructor_rec(self):
14721482
rec = self.frame.to_records(index=False)
14731483

pandas/tests/test_series.py

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -291,6 +291,15 @@ def test_constructor_pass_none(self):
291291
def test_constructor_cast(self):
292292
self.assertRaises(ValueError, Series, ['a', 'b', 'c'], dtype=float)
293293

294+
def test_constructor_dtype_nocast(self):
295+
# #1572
296+
s = Series([1, 2, 3])
297+
298+
s2 = Series(s, dtype=np.int64)
299+
300+
s2[1] = 5
301+
self.assertEquals(s[1], 5)
302+
294303
def test_constructor_dict(self):
295304
d = {'a' : 0., 'b' : 1., 'c' : 2.}
296305
result = Series(d, index=['b', 'c', 'd', 'a'])

0 commit comments

Comments
 (0)