Skip to content

Commit 2a00574

Browse files
committed
Merge pull request pandas-dev#6548 from jreback/loc_setitem
BUG: Bug in setitem with loc on mixed integer Indexes (GH6546)
2 parents fc07edb + 148abe6 commit 2a00574

File tree

4 files changed

+44
-19
lines changed

4 files changed

+44
-19
lines changed

doc/source/release.rst

+1
Original file line numberDiff line numberDiff line change
@@ -200,6 +200,7 @@ Bug Fixes
200200
- Regression from 0.13 in the treatmenet of numpy ``datetime64`` non-ns dtypes in Series creation (:issue:`6529`)
201201
- ``.names`` attribute of MultiIndexes passed to ``set_index`` are now preserved (:issue:`6459`).
202202
- Bug in setitem with a duplicate index and an alignable rhs (:issue:`6541`)
203+
- Bug in setitem with loc on mixed integer Indexes (:issue:`6546`)
203204

204205
pandas 0.13.1
205206
-------------

pandas/core/index.py

+23
Original file line numberDiff line numberDiff line change
@@ -555,6 +555,29 @@ def _convert_list_indexer(self, key, typ=None):
555555
""" convert a list indexer. these should be locations """
556556
return key
557557

558+
def _convert_list_indexer_for_mixed(self, keyarr, typ=None):
559+
""" passed a key that is tuplesafe that is integer based
560+
and we have a mixed index (e.g. number/labels). figure out
561+
the indexer. return None if we can't help
562+
"""
563+
if com.is_integer_dtype(keyarr) and not self.is_floating():
564+
if self.inferred_type != 'integer':
565+
keyarr = np.where(keyarr < 0,
566+
len(self) + keyarr, keyarr)
567+
568+
if self.inferred_type == 'mixed-integer':
569+
indexer = self.get_indexer(keyarr)
570+
if (indexer >= 0).all():
571+
return indexer
572+
573+
from pandas.core.indexing import _maybe_convert_indices
574+
return _maybe_convert_indices(indexer, len(self))
575+
576+
elif not self.inferred_type == 'integer':
577+
return keyarr
578+
579+
return None
580+
558581
def _convert_indexer_error(self, key, msg=None):
559582
if msg is None:
560583
msg = 'label'

pandas/core/indexing.py

+7-19
Original file line numberDiff line numberDiff line change
@@ -911,20 +911,10 @@ def _reindex(keys, level=None):
911911
# asarray can be unsafe, NumPy strings are weird
912912
keyarr = _asarray_tuplesafe(key)
913913

914-
if is_integer_dtype(keyarr) and not labels.is_floating():
915-
if labels.inferred_type != 'integer':
916-
keyarr = np.where(keyarr < 0,
917-
len(labels) + keyarr, keyarr)
918-
919-
if labels.inferred_type == 'mixed-integer':
920-
indexer = labels.get_indexer(keyarr)
921-
if (indexer >= 0).all():
922-
self.obj.take(indexer, axis=axis, convert=True)
923-
else:
924-
return self.obj.take(keyarr, axis=axis)
925-
elif not labels.inferred_type == 'integer':
926-
927-
return self.obj.take(keyarr, axis=axis)
914+
# handle a mixed integer scenario
915+
indexer = labels._convert_list_indexer_for_mixed(keyarr, typ=self.name)
916+
if indexer is not None:
917+
return self.obj.take(indexer, axis=axis)
928918

929919
# this is not the most robust, but...
930920
if (isinstance(labels, MultiIndex) and
@@ -1064,11 +1054,9 @@ def _convert_to_indexer(self, obj, axis=0, is_setter=False):
10641054
objarr = _asarray_tuplesafe(obj)
10651055

10661056
# If have integer labels, defer to label-based indexing
1067-
if is_integer_dtype(objarr) and not is_int_index:
1068-
if labels.inferred_type != 'integer':
1069-
objarr = np.where(objarr < 0,
1070-
len(labels) + objarr, objarr)
1071-
return objarr
1057+
indexer = labels._convert_list_indexer_for_mixed(objarr, typ=self.name)
1058+
if indexer is not None:
1059+
return indexer
10721060

10731061
# this is not the most robust, but...
10741062
if (isinstance(labels, MultiIndex) and

pandas/tests/test_indexing.py

+13
Original file line numberDiff line numberDiff line change
@@ -835,6 +835,19 @@ def test_loc_setitem_frame(self):
835835
expected = DataFrame(dict(A = Series(val1,index=keys1), B = Series(val2,index=keys2))).reindex(index=index)
836836
assert_frame_equal(df, expected)
837837

838+
# GH 6546
839+
# setting with mixed labels
840+
df = DataFrame({1:[1,2],2:[3,4],'a':['a','b']})
841+
842+
result = df.loc[0,[1,2]]
843+
expected = Series([1,3],index=[1,2],dtype=object)
844+
assert_series_equal(result,expected)
845+
846+
expected = DataFrame({1:[5,2],2:[6,4],'a':['a','b']})
847+
df.loc[0,[1,2]] = [5,6]
848+
assert_frame_equal(df, expected)
849+
850+
838851
def test_loc_setitem_frame_multiples(self):
839852

840853
# multiple setting

0 commit comments

Comments
 (0)