From 6706e93df81a5ea7a4e3b56c292b54beba46958c Mon Sep 17 00:00:00 2001 From: jreback Date: Tue, 21 May 2013 12:10:30 -0400 Subject: [PATCH] BUG: Fix alignment issue when setitem in a mixed-DataFrame with a Series (GH3668_) TST: missing test frame in test_indexing --- RELEASE.rst | 4 +++- pandas/core/common.py | 5 ++++- pandas/core/indexing.py | 5 +++-- pandas/tests/test_frame.py | 6 ------ pandas/tests/test_indexing.py | 23 ++++++++++++++++++++++- 5 files changed, 32 insertions(+), 11 deletions(-) diff --git a/RELEASE.rst b/RELEASE.rst index 3940cd6d10b51..436f9d8b833a3 100644 --- a/RELEASE.rst +++ b/RELEASE.rst @@ -146,7 +146,8 @@ pandas 0.11.1 - Correctly parse date columns with embedded (nan/NaT) into datetime64[ns] dtype in ``read_csv`` when ``parse_dates`` is specified (GH3062_) - Fix not consolidating before to_csv (GH3624_) - - Fix alignment issue when setitem in a DataFrame with a piece of a DataFrame (GH3626_) + - Fix alignment issue when setitem in a DataFrame with a piece of a DataFrame (GH3626_) or + a mixed DataFrame and a Series (GH3668_) - Fix plotting of unordered DatetimeIndex (GH3601_) - ``sql.write_frame`` failing when writing a single column to sqlite (GH3628_), thanks to @stonebig @@ -217,6 +218,7 @@ pandas 0.11.1 .. _GH3141: https://github.com/pydata/pandas/issues/3141 .. _GH3628: https://github.com/pydata/pandas/issues/3628 .. _GH3638: https://github.com/pydata/pandas/issues/3638 +.. _GH3668: https://github.com/pydata/pandas/issues/3668 .. _GH3605: https://github.com/pydata/pandas/issues/3605 .. _GH3606: https://github.com/pydata/pandas/issues/3606 .. _GH3659: https://github.com/pydata/pandas/issues/3659 diff --git a/pandas/core/common.py b/pandas/core/common.py index a52c932b30ba4..29516f9d2d4a3 100644 --- a/pandas/core/common.py +++ b/pandas/core/common.py @@ -851,6 +851,7 @@ def _maybe_upcast_indexer(result, indexer, other, dtype=None): return the result and a changed flag """ + original_dtype = result.dtype def changeit(): # our type is wrong here, need to upcast r, fill_value = _maybe_upcast(result, fill_value=other, dtype=dtype, copy=True) @@ -861,9 +862,11 @@ def changeit(): # if we hit this then we still have an incompatible type r[indexer] = fill_value + # if we have changed to floats, might want to cast back if we can + r = _possibly_downcast_to_dtype(r,original_dtype) return r, True - new_dtype, fill_value = _maybe_promote(result.dtype,other) + new_dtype, fill_value = _maybe_promote(original_dtype,other) if new_dtype != result.dtype: return changeit() diff --git a/pandas/core/indexing.py b/pandas/core/indexing.py index 41f20cbcc15ac..f7187b7ae5d61 100644 --- a/pandas/core/indexing.py +++ b/pandas/core/indexing.py @@ -143,7 +143,7 @@ def setter(item, v): else: setter(item, np.nan) - # we have an equal len ndarray + # we have an equal len ndarray to our labels elif isinstance(value, np.ndarray) and value.ndim == 2: if len(labels) != value.shape[1]: raise ValueError('Must have equal len keys and value when' @@ -153,7 +153,8 @@ def setter(item, v): setter(item, value[:,i]) # we have an equal len list/ndarray - elif len(labels) == 1 and len(self.obj[labels[0]]) == len(value): + elif len(labels) == 1 and ( + len(self.obj[labels[0]]) == len(value) or len(plane_indexer[0]) == len(value)): setter(labels[0], value) # per label values diff --git a/pandas/tests/test_frame.py b/pandas/tests/test_frame.py index 50bddb6ecd85c..fddbbf93552b3 100644 --- a/pandas/tests/test_frame.py +++ b/pandas/tests/test_frame.py @@ -938,12 +938,6 @@ def test_getitem_setitem_non_ix_labels(self): assert_frame_equal(result, expected) assert_frame_equal(result2, expected) - def test_ix_assign_column_mixed(self): - # GH #1142 - orig = self.mixed_frame.ix[:, 'B'].copy() - self.mixed_frame.ix[:, 'B'] = self.mixed_frame.ix[:, 'B'] + 1 - assert_series_equal(self.mixed_frame.B, orig + 1) - def test_ix_multi_take(self): df = DataFrame(np.random.randn(3, 2)) rs = df.ix[df.index == 0, :] diff --git a/pandas/tests/test_indexing.py b/pandas/tests/test_indexing.py index 5891e8ac08040..ad3d150c7e0ad 100644 --- a/pandas/tests/test_indexing.py +++ b/pandas/tests/test_indexing.py @@ -881,7 +881,7 @@ def test_multi_assign(self): expected = DataFrame({'FC':['a',np.nan,'a','b','a','b'], 'PF':[0,0,0,0,1,1], - 'col1':Series([0,1,4,6,8,10],dtype='float64'), + 'col1':Series([0,1,4,6,8,10]), 'col2':[12,7,16,np.nan,20,22]}) @@ -898,6 +898,27 @@ def test_multi_assign(self): df2.ix[mask, cols]= dft.ix[mask, cols].values assert_frame_equal(df2,expected) + def test_ix_assign_column_mixed(self): + # GH #1142 + df = DataFrame(tm.getSeriesData()) + df['foo'] = 'bar' + + orig = df.ix[:, 'B'].copy() + df.ix[:, 'B'] = df.ix[:, 'B'] + 1 + assert_series_equal(df.B, orig + 1) + + # GH 3668, mixed frame with series value + df = DataFrame({'x':range(10), 'y':range(10,20),'z' : 'bar'}) + expected = df.copy() + expected.ix[0, 'y'] = 1000 + expected.ix[2, 'y'] = 1200 + expected.ix[4, 'y'] = 1400 + expected.ix[6, 'y'] = 1600 + expected.ix[8, 'y'] = 1800 + + df.ix[df.x % 2 == 0, 'y'] = df.ix[df.x % 2 == 0, 'y'] * 100 + assert_frame_equal(df,expected) + def test_iloc_mask(self): # GH 3631, iloc with a mask (of a series) should raise