Skip to content

Commit 05995f2

Browse files
committed
ENH: some integration of multi-level indexing with .ix fancy indexing
1 parent be76736 commit 05995f2

File tree

4 files changed

+36
-1
lines changed

4 files changed

+36
-1
lines changed

pandas/core/index.py

+4-1
Original file line numberDiff line numberDiff line change
@@ -625,7 +625,10 @@ def get_loc(self, key):
625625
if len(key) == self.nlevels:
626626
return self._get_tuple_loc(key)
627627
else:
628-
return slice(*self.slice_locs(key, key))
628+
result = slice(*self.slice_locs(key, key))
629+
if result.start == result.stop:
630+
raise KeyError(key)
631+
return result
629632
else:
630633
# assert(self.sortorder == 0)
631634
# slice level 0

pandas/core/indexing.py

+10
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
from pandas.core.index import MultiIndex
2+
13
import numpy as np
24

35
class _SeriesIndexer(object):
@@ -100,6 +102,14 @@ def __getitem__(self, key):
100102
return self._fancy_getitem_axis(key, axis=0)
101103

102104
def _getitem_tuple(self, key):
105+
if isinstance(self.frame.index, MultiIndex):
106+
try:
107+
return self.frame.xs(key)
108+
except KeyError:
109+
# could do something more intelligent here? like raising the
110+
# exception if each tuple value are in the levels?
111+
pass
112+
103113
if len(key) != 2:
104114
raise Exception('only length 2 tuple supported')
105115
return self._fancy_getitem_tuple(*key)

pandas/tests/test_index.py

+11
Original file line numberDiff line numberDiff line change
@@ -352,6 +352,17 @@ def test_get_loc(self):
352352
self.assert_(self.index.get_loc(('foo', 'two')) == 1)
353353
self.assert_(self.index.get_loc(('baz', 'two')) == 3)
354354
self.assertRaises(KeyError, self.index.get_loc, ('bar', 'two'))
355+
self.assertRaises(KeyError, self.index.get_loc, 'quux')
356+
357+
# 3 levels
358+
index = MultiIndex(levels=[Index(range(4)),
359+
Index(range(4)),
360+
Index(range(4))],
361+
labels=[np.array([0, 0, 1, 2, 2, 2, 3, 3]),
362+
np.array([0, 1, 0, 0, 0, 1, 0, 1]),
363+
np.array([1, 0, 1, 1, 0, 0, 1, 0])])
364+
self.assertRaises(KeyError, index.get_loc, (1, 1))
365+
self.assert_(index.get_loc((2, 0)) == slice(3, 5))
355366

356367
def test_slice_locs(self):
357368
df = tm.makeTimeDataFrame()

pandas/tests/test_multilevel.py

+11
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@ def test_getitem_simple(self):
4545
col = df['foo', 'one']
4646
assert_almost_equal(col.values, df.values[:, 0])
4747
self.assertRaises(KeyError, df.__getitem__, ('foo', 'four'))
48+
self.assertRaises(KeyError, df.__getitem__, 'foobar')
4849

4950
def test_xs(self):
5051
xs = self.frame.xs(('bar', 'two'))
@@ -60,6 +61,16 @@ def test_xs_partial(self):
6061
assert_frame_equal(result, expected)
6162
assert_frame_equal(result, result2)
6263

64+
def test_fancy_2d(self):
65+
result = self.frame.ix['foo', 'B']
66+
expected = self.frame.xs('foo')['B']
67+
assert_series_equal(result, expected)
68+
69+
ft = self.frame.T
70+
result = ft.ix['B', 'foo']
71+
expected = ft.xs('B')['foo']
72+
assert_series_equal(result, expected)
73+
6374
def test_getitem_toplevel(self):
6475
df = self.frame.T
6576

0 commit comments

Comments
 (0)