Skip to content

BUG: Bug in Panel indexing with a multi-index axis (GH 7516) #7519

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

Merged
merged 1 commit into from
Jun 20, 2014
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion doc/source/v0.14.1.txt
Original file line number Diff line number Diff line change
Expand Up @@ -166,7 +166,7 @@ Experimental
Bug Fixes
~~~~~~~~~
- Bug in ``DataFrame.where`` with a symmetric shaped frame and a passed other of a DataFrame (:issue:`7506`)

- Bug in Panel indexing with a multi-index axis (:issue:`7516`)

- Bug in timeops with non-aligned Series (:issue:`7500`)

Expand Down
26 changes: 13 additions & 13 deletions pandas/core/generic.py
Original file line number Diff line number Diff line change
Expand Up @@ -1632,11 +1632,11 @@ def _reindex_axes(self, axes, level, limit, method, fill_value, copy):
continue

# convert to an index if we are not a multi-selection
ax = self._get_axis(a)
if level is None:
labels = _ensure_index(labels)

axis = self._get_axis_number(a)
ax = self._get_axis(a)
new_index, indexer = ax.reindex(
labels, level=level, limit=limit, method=method)

Expand Down Expand Up @@ -1929,11 +1929,11 @@ def _get_bool_data(self):

def as_matrix(self, columns=None):
"""
Convert the frame to its Numpy-array representation.
Convert the frame to its Numpy-array representation.

Parameters
----------
columns: list, optional, default:None
columns: list, optional, default:None
If None, return all columns, otherwise, returns specified columns.

Returns
Expand All @@ -1942,23 +1942,23 @@ def as_matrix(self, columns=None):
If the caller is heterogeneous and contains booleans or objects,
the result will be of dtype=object. See Notes.


Notes
-----
-----
Return is NOT a Numpy-matrix, rather, a Numpy-array.

The dtype will be a lower-common-denominator dtype (implicit
upcasting); that is to say if the dtypes (even of numeric types)
are mixed, the one that accommodates all will be chosen. Use this
with care if you are not dealing with the blocks.

e.g. If the dtypes are float16 and float32, dtype will be upcast to
float32. If dtypes are int32 and uint8, dtype will be upcase to
e.g. If the dtypes are float16 and float32, dtype will be upcast to
float32. If dtypes are int32 and uint8, dtype will be upcase to
int32.

This method is provided for backwards compatibility. Generally,
it is recommended to use '.values'.

See Also
--------
pandas.DataFrame.values
Expand All @@ -1971,16 +1971,16 @@ def as_matrix(self, columns=None):
@property
def values(self):
"""Numpy representation of NDFrame

Notes
-----
The dtype will be a lower-common-denominator dtype (implicit
upcasting); that is to say if the dtypes (even of numeric types)
are mixed, the one that accommodates all will be chosen. Use this
with care if you are not dealing with the blocks.

e.g. If the dtypes are float16 and float32, dtype will be upcast to
float32. If dtypes are int32 and uint8, dtype will be upcase to
e.g. If the dtypes are float16 and float32, dtype will be upcast to
float32. If dtypes are int32 and uint8, dtype will be upcase to
int32.
"""
return self.as_matrix()
Expand Down
9 changes: 8 additions & 1 deletion pandas/core/indexing.py
Original file line number Diff line number Diff line change
Expand Up @@ -816,7 +816,7 @@ def _getitem_nested_tuple(self, tup):
# this is iterative
obj = self.obj
axis = 0
for key in tup:
for i, key in enumerate(tup):

if _is_null_slice(key):
axis += 1
Expand All @@ -833,6 +833,13 @@ def _getitem_nested_tuple(self, tup):
# has the dim of the obj changed?
# GH 7199
if obj.ndim < current_ndim:

# GH 7516
# if had a 3 dim and are going to a 2d
# axes are reversed on a DataFrame
if i >= 1 and current_ndim == 3 and obj.ndim == 2:
obj = obj.T

axis -= 1

return obj
Expand Down
11 changes: 7 additions & 4 deletions pandas/core/panel.py
Original file line number Diff line number Diff line change
Expand Up @@ -797,12 +797,15 @@ def _ixs(self, i, axis=0):
axis : int
"""

key = self._get_axis(axis)[i]
ax = self._get_axis(axis)
key = ax[i]

# xs cannot handle a non-scalar key, so just reindex here
if _is_list_like(key):
indexer = {self._get_axis_name(axis): key}
return self.reindex(**indexer)
# if we have a multi-index and a single tuple, then its a reduction (GH 7516)
if not (isinstance(ax, MultiIndex) and isinstance(key, tuple)):
if _is_list_like(key):
indexer = {self._get_axis_name(axis): key}
return self.reindex(**indexer)

# a reduction
if axis == 0:
Expand Down
10 changes: 10 additions & 0 deletions pandas/tests/test_indexing.py
Original file line number Diff line number Diff line change
Expand Up @@ -1179,6 +1179,16 @@ def f():
result2 = wd2.iloc[0,[0],[0,1,2]]
assert_frame_equal(result2,expected2)

# GH 7516
mi = MultiIndex.from_tuples([(0,'x'), (1,'y'), (2,'z')])
p = Panel(np.arange(3*3*3,dtype='int64').reshape(3,3,3), items=['a','b','c'], major_axis=mi, minor_axis=['u','v','w'])
result = p.iloc[:, 1, 0]
expected = Series([3,12,21],index=['a','b','c'], name='u')
assert_series_equal(result,expected)

result = p.loc[:, (1,'y'), 'u']
assert_series_equal(result,expected)

def test_iloc_getitem_doc_issue(self):

# multi axis slicing issue with single block
Expand Down