Skip to content

Commit 5fb09bf

Browse files
committed
Merge pull request #3670 from jreback/set_with_series
BUG: Fix alignment issue when setitem in a mixed-DataFrame with a Series (GH3668)
2 parents 4ccba4d + 6706e93 commit 5fb09bf

File tree

5 files changed

+32
-11
lines changed

5 files changed

+32
-11
lines changed

RELEASE.rst

+3-1
Original file line numberDiff line numberDiff line change
@@ -146,7 +146,8 @@ pandas 0.11.1
146146
- Correctly parse date columns with embedded (nan/NaT) into datetime64[ns] dtype in ``read_csv``
147147
when ``parse_dates`` is specified (GH3062_)
148148
- Fix not consolidating before to_csv (GH3624_)
149-
- Fix alignment issue when setitem in a DataFrame with a piece of a DataFrame (GH3626_)
149+
- Fix alignment issue when setitem in a DataFrame with a piece of a DataFrame (GH3626_) or
150+
a mixed DataFrame and a Series (GH3668_)
150151
- Fix plotting of unordered DatetimeIndex (GH3601_)
151152
- ``sql.write_frame`` failing when writing a single column to sqlite (GH3628_),
152153
thanks to @stonebig
@@ -217,6 +218,7 @@ pandas 0.11.1
217218
.. _GH3141: https://github.com/pydata/pandas/issues/3141
218219
.. _GH3628: https://github.com/pydata/pandas/issues/3628
219220
.. _GH3638: https://github.com/pydata/pandas/issues/3638
221+
.. _GH3668: https://github.com/pydata/pandas/issues/3668
220222
.. _GH3605: https://github.com/pydata/pandas/issues/3605
221223
.. _GH3606: https://github.com/pydata/pandas/issues/3606
222224
.. _GH3659: https://github.com/pydata/pandas/issues/3659

pandas/core/common.py

+4-1
Original file line numberDiff line numberDiff line change
@@ -851,6 +851,7 @@ def _maybe_upcast_indexer(result, indexer, other, dtype=None):
851851
return the result and a changed flag
852852
"""
853853

854+
original_dtype = result.dtype
854855
def changeit():
855856
# our type is wrong here, need to upcast
856857
r, fill_value = _maybe_upcast(result, fill_value=other, dtype=dtype, copy=True)
@@ -861,9 +862,11 @@ def changeit():
861862
# if we hit this then we still have an incompatible type
862863
r[indexer] = fill_value
863864

865+
# if we have changed to floats, might want to cast back if we can
866+
r = _possibly_downcast_to_dtype(r,original_dtype)
864867
return r, True
865868

866-
new_dtype, fill_value = _maybe_promote(result.dtype,other)
869+
new_dtype, fill_value = _maybe_promote(original_dtype,other)
867870
if new_dtype != result.dtype:
868871
return changeit()
869872

pandas/core/indexing.py

+3-2
Original file line numberDiff line numberDiff line change
@@ -143,7 +143,7 @@ def setter(item, v):
143143
else:
144144
setter(item, np.nan)
145145

146-
# we have an equal len ndarray
146+
# we have an equal len ndarray to our labels
147147
elif isinstance(value, np.ndarray) and value.ndim == 2:
148148
if len(labels) != value.shape[1]:
149149
raise ValueError('Must have equal len keys and value when'
@@ -153,7 +153,8 @@ def setter(item, v):
153153
setter(item, value[:,i])
154154

155155
# we have an equal len list/ndarray
156-
elif len(labels) == 1 and len(self.obj[labels[0]]) == len(value):
156+
elif len(labels) == 1 and (
157+
len(self.obj[labels[0]]) == len(value) or len(plane_indexer[0]) == len(value)):
157158
setter(labels[0], value)
158159

159160
# per label values

pandas/tests/test_frame.py

-6
Original file line numberDiff line numberDiff line change
@@ -938,12 +938,6 @@ def test_getitem_setitem_non_ix_labels(self):
938938
assert_frame_equal(result, expected)
939939
assert_frame_equal(result2, expected)
940940

941-
def test_ix_assign_column_mixed(self):
942-
# GH #1142
943-
orig = self.mixed_frame.ix[:, 'B'].copy()
944-
self.mixed_frame.ix[:, 'B'] = self.mixed_frame.ix[:, 'B'] + 1
945-
assert_series_equal(self.mixed_frame.B, orig + 1)
946-
947941
def test_ix_multi_take(self):
948942
df = DataFrame(np.random.randn(3, 2))
949943
rs = df.ix[df.index == 0, :]

pandas/tests/test_indexing.py

+22-1
Original file line numberDiff line numberDiff line change
@@ -881,7 +881,7 @@ def test_multi_assign(self):
881881

882882
expected = DataFrame({'FC':['a',np.nan,'a','b','a','b'],
883883
'PF':[0,0,0,0,1,1],
884-
'col1':Series([0,1,4,6,8,10],dtype='float64'),
884+
'col1':Series([0,1,4,6,8,10]),
885885
'col2':[12,7,16,np.nan,20,22]})
886886

887887

@@ -898,6 +898,27 @@ def test_multi_assign(self):
898898
df2.ix[mask, cols]= dft.ix[mask, cols].values
899899
assert_frame_equal(df2,expected)
900900

901+
def test_ix_assign_column_mixed(self):
902+
# GH #1142
903+
df = DataFrame(tm.getSeriesData())
904+
df['foo'] = 'bar'
905+
906+
orig = df.ix[:, 'B'].copy()
907+
df.ix[:, 'B'] = df.ix[:, 'B'] + 1
908+
assert_series_equal(df.B, orig + 1)
909+
910+
# GH 3668, mixed frame with series value
911+
df = DataFrame({'x':range(10), 'y':range(10,20),'z' : 'bar'})
912+
expected = df.copy()
913+
expected.ix[0, 'y'] = 1000
914+
expected.ix[2, 'y'] = 1200
915+
expected.ix[4, 'y'] = 1400
916+
expected.ix[6, 'y'] = 1600
917+
expected.ix[8, 'y'] = 1800
918+
919+
df.ix[df.x % 2 == 0, 'y'] = df.ix[df.x % 2 == 0, 'y'] * 100
920+
assert_frame_equal(df,expected)
921+
901922
def test_iloc_mask(self):
902923

903924
# GH 3631, iloc with a mask (of a series) should raise

0 commit comments

Comments
 (0)