Skip to content

Commit

Permalink
ENH: add level keyword to drop method, GH #159
Browse files Browse the repository at this point in the history
  • Loading branch information
wesm committed Mar 13, 2012
1 parent 381ef5d commit fe065ce
Show file tree
Hide file tree
Showing 3 changed files with 55 additions and 18 deletions.
14 changes: 11 additions & 3 deletions pandas/core/generic.py
Original file line number Diff line number Diff line change
Expand Up @@ -156,22 +156,30 @@ def select(self, crit, axis=0):

return self.reindex(**{axis_name : new_axis})

def drop(self, labels, axis=0):
def drop(self, labels, axis=0, level=None):
"""
Return new object with labels in requested axis removed
Parameters
----------
labels : array-like
axis : int
level : int or name, default None
For MultiIndex
Returns
-------
dropped : type of caller
"""
axis_name = self._get_axis_name(axis)
axis = self._get_axis(axis)
new_axis = axis.drop(labels)

if level is not None:
assert(isinstance(axis, MultiIndex))
new_axis = axis.drop(labels, level=level)
else:
new_axis = axis.drop(labels)

return self.reindex(**{axis_name : new_axis})

def sort_index(self, axis=0, ascending=True):
Expand Down Expand Up @@ -316,7 +324,7 @@ def __delitem__(self, key):
Delete item
"""
deleted = False
if (hasattr(self,'columns') and
if (hasattr(self,'columns') and
isinstance(self.columns, MultiIndex)
and key not in self.columns):
# Allow shorthand to delete all columns whose first len(key)
Expand Down
15 changes: 14 additions & 1 deletion pandas/core/index.py
Original file line number Diff line number Diff line change
Expand Up @@ -1446,19 +1446,23 @@ def append(self, other):
def argsort(self, *args, **kwargs):
return self.values.argsort()

def drop(self, labels):
def drop(self, labels, level=None):
"""
Make new MultiIndex with passed list of labels deleted
Parameters
----------
labels : array-like
Must be a list of tuples
level : int or name, default None
Returns
-------
dropped : MultiIndex
"""
if level is not None:
return self._drop_from_level(labels, level)

try:
if not isinstance(labels, np.ndarray):
labels = com._asarray_tuplesafe(labels)
Expand All @@ -1481,6 +1485,15 @@ def drop(self, labels):

return self.delete(inds)

def _drop_from_level(self, labels, level):
i = self._get_level_number(level)
index = self.levels[i]
values = index.get_indexer(labels)

mask = -lib.ismember(self.labels[i], set(values))

return self[mask]

def droplevel(self, level=0):
"""
Return Index with requested level removed. If MultiIndex has only 2
Expand Down
44 changes: 30 additions & 14 deletions pandas/tests/test_multilevel.py
Original file line number Diff line number Diff line change
Expand Up @@ -1118,61 +1118,61 @@ def test_mixed_depth_get(self):
tuples.sort()
index = MultiIndex.from_tuples(tuples)
df = DataFrame(randn(4,6),columns = index)

result = df['a']
expected = df['a','','']
assert_series_equal(result, expected)
self.assertEquals(result.name, 'a')

result = df['routine1','result1']
expected = df['routine1','result1','']
assert_series_equal(result, expected)
self.assertEquals(result.name, ('routine1', 'result1'))

def test_mixed_depth_insert(self):
def test_mixed_depth_insert(self):
arrays = [[ 'a', 'top', 'top', 'routine1', 'routine1', 'routine2'],
[ '', 'OD', 'OD', 'result1', 'result2', 'result1'],
[ '', 'wx', 'wy', '', '', '']]

tuples = zip(*arrays)
tuples.sort()
index = MultiIndex.from_tuples(tuples)
df = DataFrame(randn(4,6),columns = index)
df = DataFrame(randn(4,6),columns = index)

result = df.copy()
expected = df.copy()
result['b'] = [1,2,3,4]
expected['b','',''] = [1,2,3,4]
assert_frame_equal(result, expected)
def test_mixed_depth_drop(self):

def test_mixed_depth_drop(self):
arrays = [[ 'a', 'top', 'top', 'routine1', 'routine1', 'routine2'],
[ '', 'OD', 'OD', 'result1', 'result2', 'result1'],
[ '', 'wx', 'wy', '', '', '']]

tuples = zip(*arrays)
tuples.sort()
index = MultiIndex.from_tuples(tuples)
df = DataFrame(randn(4,6),columns = index)
df = DataFrame(randn(4,6),columns = index)

result = df.drop('a',axis=1)
expected = df.drop([('a','','')],axis=1)
assert_frame_equal(expected, result)

result = df.drop(['top'],axis=1)
expected = df.drop([('top','OD','wx')], axis=1)
expected = expected.drop([('top','OD','wy')], axis=1)
assert_frame_equal(expected, result)
def test_mixed_depth_pop(self):

def test_mixed_depth_pop(self):
arrays = [[ 'a', 'top', 'top', 'routine1', 'routine1', 'routine2'],
[ '', 'OD', 'OD', 'result1', 'result2', 'result1'],
[ '', 'wx', 'wy', '', '', '']]

tuples = zip(*arrays)
tuples.sort()
index = MultiIndex.from_tuples(tuples)
df = DataFrame(randn(4,6),columns = index)
df = DataFrame(randn(4,6),columns = index)

df1 = df.copy()
df2 = df.copy()
Expand All @@ -1181,14 +1181,30 @@ def test_mixed_depth_pop(self):
assert_series_equal(expected, result)
assert_frame_equal(df1, df2)
self.assertEquals(result.name,'a')

expected = df1['top']
df1 = df1.drop(['top'],axis=1)
result = df2.pop('top')
assert_frame_equal(expected, result)
assert_frame_equal(df1, df2)



def test_drop_level(self):
result = self.frame.drop(['bar', 'qux'], level='first')
expected = self.frame.ix[[0, 1, 2, 5, 6]]
assert_frame_equal(result, expected)

result = self.frame.drop(['two'], level='second')
expected = self.frame.ix[[0, 2, 3, 6, 7, 9]]
assert_frame_equal(result, expected)

result = self.frame.T.drop(['bar', 'qux'], axis=1, level='first')
expected = self.frame.ix[[0, 1, 2, 5, 6]].T
assert_frame_equal(result, expected)

result = self.frame.T.drop(['two'], axis=1, level='second')
expected = self.frame.ix[[0, 2, 3, 6, 7, 9]].T
assert_frame_equal(result, expected)

if __name__ == '__main__':

# unittest.main()
Expand Down

0 comments on commit fe065ce

Please sign in to comment.