Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

REGR: Series access with Index of tuples/frozenset #36147

Merged
merged 12 commits into from
Sep 12, 2020
2 changes: 2 additions & 0 deletions doc/source/whatsnew/v1.1.3.rst
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@ including other versions of pandas.

Fixed regressions
~~~~~~~~~~~~~~~~~
- Fixed regression in :meth:`Series.__getitem__` incorrectly raising when the input was a tuple (:issue:`35534`)
- Fixed regression in :meth:`Series.__getitem__` incorrectly raising when the input was a frozenset (:issue:`35747`)
-

.. ---------------------------------------------------------------------------
Expand Down
22 changes: 11 additions & 11 deletions pandas/core/series.py
Original file line number Diff line number Diff line change
Expand Up @@ -887,21 +887,19 @@ def __getitem__(self, key):
elif key_is_scalar:
return self._get_value(key)

if (
isinstance(key, tuple)
and is_hashable(key)
and isinstance(self.index, MultiIndex)
):
if is_hashable(key):
# Otherwise index.get_value will raise InvalidIndexError
rhshadrach marked this conversation as resolved.
Show resolved Hide resolved
try:
# For labels that don't resolve as scalars like tuples and frozensets
result = self._get_value(key)

return result

except KeyError:
# We still have the corner case where this tuple is a key
# in the first level of our MultiIndex
return self._get_values_tuple(key)
if isinstance(key, tuple) and isinstance(self.index, MultiIndex):
# We still have the corner case where a tuple is a key
# in the first level of our MultiIndex
return self._get_values_tuple(key)
rhshadrach marked this conversation as resolved.
Show resolved Hide resolved

if is_iterator(key):
key = list(key)
Expand Down Expand Up @@ -961,7 +959,7 @@ def _get_values_tuple(self, key):
return result

if not isinstance(self.index, MultiIndex):
raise ValueError("Can only tuple-index with a MultiIndex")
raise ValueError("key of type tuple not found and not a MultiIndex")

# If key is contained, would have returned by now
indexer, new_index = self.index.get_loc_level(key)
Expand Down Expand Up @@ -1015,9 +1013,11 @@ def __setitem__(self, key, value):
# GH#12862 adding an new key to the Series
self.loc[key] = value

except TypeError as e:
except TypeError as err:
if isinstance(key, tuple) and not isinstance(self.index, MultiIndex):
raise ValueError("Can only tuple-index with a MultiIndex") from e
raise ValueError(
"key of type tuple not found and not a MultiIndex"
) from err

if com.is_bool_indexer(key):
key = check_bool_indexer(self.index, key)
Expand Down
21 changes: 20 additions & 1 deletion pandas/tests/series/indexing/test_indexing.py
Original file line number Diff line number Diff line change
Expand Up @@ -383,7 +383,7 @@ def test_2d_to_1d_assignment_raises():
@pytest.mark.filterwarnings("ignore:Using a non-tuple:FutureWarning")
def test_basic_getitem_setitem_corner(datetime_series):
# invalid tuples, e.g. td.ts[:, None] vs. td.ts[:, 2]
msg = "Can only tuple-index with a MultiIndex"
msg = "key of type tuple not found and not a MultiIndex"
with pytest.raises(ValueError, match=msg):
datetime_series[:, 2]
with pytest.raises(ValueError, match=msg):
Expand Down Expand Up @@ -942,3 +942,22 @@ def assert_slices_equivalent(l_slc, i_slc):
for key2 in [keystr2, box(keystr2)]:
assert_slices_equivalent(SLC[key2:key:-1], SLC[13:8:-1])
assert_slices_equivalent(SLC[key:key2:-1], SLC[0:0:-1])


def test_tuple_index():
# GH 35534 - Selecting values when a Series has an Index of tuples
s = pd.Series([1, 2], index=[("a",), ("b",)])
assert s[("a",)] == 1
assert s[("b",)] == 2
s[("b",)] = 3
assert s[("b",)] == 3


def test_frozenset_index():
# GH35747 - Selecting values when a Series has an Index of frozenset
idx0, idx1 = frozenset("a"), frozenset("b")
s = pd.Series([1, 2], index=[idx0, idx1])
assert s[idx0] == 1
assert s[idx1] == 2
s[idx1] = 3
assert s[idx1] == 3