Skip to content

Commit f735a67

Browse files
committed
ENH: wrap up API changes and testing around #592
1 parent 42ce8ff commit f735a67

File tree

4 files changed

+63
-86
lines changed

4 files changed

+63
-86
lines changed

pandas/core/indexing.py

Lines changed: 17 additions & 77 deletions
Original file line numberDiff line numberDiff line change
@@ -31,11 +31,14 @@ def __getitem__(self, key):
3131
else:
3232
return self._getitem_axis(key, axis=0)
3333

34-
def _getitem_xs(self, idx, axis=0):
34+
def _get(self, label, axis=0):
3535
try:
36-
return self.obj.xs(idx, axis=axis, copy=False)
36+
return self.obj.xs(label, axis=axis, copy=False)
3737
except Exception:
38-
return self.obj.xs(idx, axis=axis, copy=True)
38+
return self.obj.xs(label, axis=axis, copy=True)
39+
40+
def _slice(self, obj, axis=0):
41+
return self.obj._slice(obj, axis=axis)
3942

4043
def __setitem__(self, key, value):
4144
# kludgetastic
@@ -93,7 +96,7 @@ def _getitem_tuple(self, tup):
9396
# a bit kludgy
9497
if isinstance(self.obj._get_axis(0), MultiIndex):
9598
try:
96-
return self._getitem_xs(tup, axis=0)
99+
return self._get(tup, axis=0)
97100
except (KeyError, TypeError):
98101
pass
99102

@@ -153,21 +156,21 @@ def _getitem_axis(self, key, axis=0):
153156
if com.is_integer(key):
154157
if isinstance(labels, MultiIndex):
155158
try:
156-
return self._getitem_xs(key, axis=0)
159+
return self._get(key, axis=0)
157160
except (KeyError, TypeError):
158161
if _is_integer_index(self.obj.index.levels[0]):
159162
raise
160163

161164
if not is_int_index:
162165
idx = labels[key]
163166

164-
return self._getitem_xs(idx, axis=0)
167+
return self._get(idx, axis=0)
165168
else:
166169
labels = self.obj._get_axis(axis)
167170
lab = key
168171
if com.is_integer(key) and not _is_integer_index(labels):
169172
lab = labels[key]
170-
return self._getitem_xs(lab, axis=axis)
173+
return self._get(lab, axis=axis)
171174

172175
def _getitem_iterable(self, key, axis=0):
173176
labels = self.obj._get_axis(axis)
@@ -298,7 +301,7 @@ def _get_slice_axis(self, slice_obj, axis=0):
298301
if not _need_slice(slice_obj):
299302
return obj
300303

301-
return obj._slice(slicer, axis=axis)
304+
return self._slice(slicer, axis=axis)
302305

303306
def _is_integer_slice(obj):
304307
def _crit(v):
@@ -327,77 +330,14 @@ class _SeriesIndexer(_NDFrameIndexer):
327330
>>> ts.ix[date1:date2] = 0
328331
"""
329332

330-
def __getitem__(self, key):
331-
ax = self.obj.index
332-
333-
if isinstance(key, slice):
334-
key = self._convert_slice(key)
335-
336-
if isinstance(ax, MultiIndex):
337-
try:
338-
# key = ax.get_loc(key)
339-
return self._get_default(key)
340-
except Exception:
341-
pass
342-
343-
if _isboolarr(key):
344-
self._check_boolean_key(key)
345-
elif isinstance(key, slice):
346-
pass
347-
elif _is_list_like(key):
348-
return self._get_list_like(key)
349-
return self._get_default(key)
350-
351-
def __setitem__(self, key, value):
352-
ax = self.obj.index
353-
if isinstance(ax, MultiIndex):
354-
try:
355-
key = ax.get_loc(key)
356-
self._set_default(key, value)
357-
return
358-
except Exception:
359-
pass
360-
361-
if _isboolarr(key):
362-
self._check_boolean_key(key)
363-
elif isinstance(key, slice):
364-
key = self._convert_slice(key)
365-
elif _is_list_like(key):
366-
return self._set_list_like(key, value)
367-
return self._set_default(key, value)
368-
369-
def _check_boolean_key(self, key):
370-
if _is_series(key):
371-
if not key.index.equals(self.obj.index):
372-
raise IndexingError('Cannot use boolean index with '
373-
'misaligned or unequal labels')
374-
375-
def _convert_slice(self, key):
376-
if _is_label_slice(self.obj.index, key):
377-
i, j = self.obj.index.slice_locs(key.start, key.stop)
378-
key = slice(i, j)
379-
return key
380-
381-
def _get_default(self, key):
382-
return self.obj[key]
383-
384-
def _get_list_like(self, key):
385-
if isinstance(self.obj.index, MultiIndex):
386-
try:
387-
return self.obj[key]
388-
except (KeyError, TypeError, IndexError):
389-
pass
390-
return self.obj.reindex(key)
333+
def _get(self, label, axis=0):
334+
return self.obj[label]
391335

392-
def _set_default(self, key, value):
393-
self.obj[key] = value
336+
def _slice(self, obj, axis=0):
337+
return self.obj[obj]
394338

395-
def _set_list_like(self, key, value):
396-
inds = self.obj.index.get_indexer(key)
397-
mask = inds == -1
398-
if mask.any():
399-
raise IndexingError('Indices %s not found' % key[mask])
400-
self.obj.put(inds, value)
339+
def _setitem_with_indexer(self, indexer, value):
340+
self.obj[indexer] = value
401341

402342
def _is_series(obj):
403343
from pandas.core.series import Series

pandas/core/series.py

Lines changed: 6 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -295,7 +295,7 @@ def __getitem__(self, key):
295295
pass
296296

297297
if index.inferred_type == 'integer':
298-
raise # AmbiguousIndexError(key)
298+
raise
299299

300300
try:
301301
return _gin.get_value_at(self, key)
@@ -307,26 +307,24 @@ def __getitem__(self, key):
307307
except TypeError:
308308
pass
309309

310-
def _index_with(indexer):
311-
return Series(self.values[indexer], index=self.index[indexer],
312-
name=self.name)
313-
314310
# boolean
315311

316312
# special handling of boolean data with NAs stored in object
317313
# arrays. Since we can't represent NA with dtype=bool
318314
if _is_bool_indexer(key):
319315
key = self._check_bool_indexer(key)
320316
key = np.asarray(key, dtype=bool)
321-
return _index_with(key)
322317

323-
# other: fancy integer or otherwise
318+
return self._index_with(key)
324319

320+
def _index_with(self, key):
321+
# other: fancy integer or otherwise
325322
# [slice(0, 5, None)] will break if you convert to ndarray,
326323
# e.g. as requested by np.median
327324

328325
try:
329-
return _index_with(key)
326+
return Series(self.values[key], index=self.index[key],
327+
name=self.name)
330328
except Exception:
331329
return self.values[key]
332330

pandas/tests/test_series.py

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -472,6 +472,13 @@ def test_setslice(self):
472472
self.assertEqual(len(sl), len(sl.index))
473473
self.assertEqual(len(sl.index.indexMap), len(sl.index))
474474

475+
# def test_getitem_reindex(self):
476+
# indices = self.ts.index[[5, 10, 15]]
477+
478+
# result = self.ts[indices]
479+
# expected = self.ts.reindex(indices)
480+
# assert_series_equal(result, expected)
481+
475482
def test_ix_getitem(self):
476483
inds = self.series.index[[3,4,7]]
477484
assert_series_equal(self.series.ix[inds], self.series.reindex(inds))
@@ -491,6 +498,39 @@ def test_ix_getitem(self):
491498
self.assertEquals(self.ts.ix[d1], self.ts[d1])
492499
self.assertEquals(self.ts.ix[d2], self.ts[d2])
493500

501+
def test_ix_getitem_not_monotonic(self):
502+
d1, d2 = self.ts.index[[5, 15]]
503+
504+
ts2 = self.ts[::2][::-1]
505+
506+
self.assertRaises(KeyError, ts2.ix.__getitem__, slice(d1, d2))
507+
self.assertRaises(KeyError, ts2.ix.__setitem__, slice(d1, d2), 0)
508+
509+
def test_ix_getitem_setitem_integer_slice_keyerrors(self):
510+
s = Series(np.random.randn(10), index=range(0, 20, 2))
511+
512+
# this is OK
513+
cp = s.copy()
514+
cp.ix[4:10] = 0
515+
self.assert_((cp.ix[4:10] == 0).all())
516+
517+
# so is this
518+
cp = s.copy()
519+
cp.ix[3:11] = 0
520+
self.assert_((cp.ix[3:11] == 0).values.all())
521+
522+
result = s.ix[4:10]
523+
result2 = s.ix[3:11]
524+
expected = s.reindex([4, 6, 8, 10])
525+
526+
assert_series_equal(result, expected)
527+
assert_series_equal(result2, expected)
528+
529+
# non-monotonic, raise KeyError
530+
s2 = s[::-1]
531+
self.assertRaises(KeyError, s2.ix.__getitem__, slice(3, 11))
532+
self.assertRaises(KeyError, s2.ix.__setitem__, slice(3, 11), 0)
533+
494534
def test_ix_getitem_iterator(self):
495535
idx = iter(self.series.index[:10])
496536
result = self.series.ix[idx]

pandas/tools/tests/test_pivot.py

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -80,7 +80,6 @@ def test_pivot_multi_functions(self):
8080
expected = concat([means, stds], keys=['mean', 'std'], axis=1)
8181
tm.assert_frame_equal(result, expected)
8282

83-
8483
def test_margins(self):
8584
def _check_output(res, col, rows=['A', 'B'], cols=['C']):
8685
cmarg = res['All'][:-1]

0 commit comments

Comments
 (0)