Skip to content

Commit b32165c

Browse files
chrisjbillingtonwesm
authored andcommitted
Tests for 'mixed depth' hierarchical columns.
Tests for getting, setting, dropping and popping columns from dataframes which have MultiIndexed columns containing some empty strings at the lower levels, by indexing with only the upper levels. Also modified NDFrame._set_item to use the same shorthand.
1 parent 428896d commit b32165c

File tree

2 files changed

+90
-3
lines changed

2 files changed

+90
-3
lines changed

pandas/core/generic.py

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -291,6 +291,13 @@ def _clear_item_cache(self):
291291
self._item_cache.clear()
292292

293293
def _set_item(self, key, value):
294+
if isinstance(self.columns, MultiIndex):
295+
# Pad the key with empty strings if lower levels of the key
296+
# aren't specified:
297+
if not isinstance(key, tuple):
298+
key = (key,)
299+
if len(key) != self.columns.nlevels:
300+
key += ('',)*(self.columns.nlevels - len(key))
294301
self._data.set(key, value)
295302

296303
try:
@@ -303,9 +310,9 @@ def __delitem__(self, key):
303310
Delete item
304311
"""
305312
deleted = False
306-
if key not in self.columns:
307-
# If column labels are tuples, allow shorthand to delete
308-
# all columns whose first len(key) elements match key:
313+
if isinstance(self.columns, MultiIndex) and key not in self.columns:
314+
# Allow shorthand to delete all columns whose first len(key)
315+
# elements match key:
309316
if not isinstance(key,tuple):
310317
key = (key,)
311318
for col in self.columns:

pandas/tests/test_multilevel.py

Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1083,6 +1083,86 @@ def test_int_series_slicing(self):
10831083
expected = self.ymd.reindex(s.index[5:])
10841084
assert_frame_equal(result, expected)
10851085

1086+
def test_mixed_depth_get(self):
1087+
arrays = [[ 'a', 'top', 'top', 'routine1', 'routine1', 'routine2'],
1088+
[ '', 'OD', 'OD', 'result1', 'result2', 'result1'],
1089+
[ '', 'wx', 'wy', '', '', '']]
1090+
1091+
tuples = zip(*arrays)
1092+
tuples.sort()
1093+
index = MultiIndex.from_tuples(tuples)
1094+
df = DataFrame(randn(4,6),columns = index)
1095+
1096+
result = df['a']
1097+
expected = df['a','','']
1098+
assert_series_equal(result, expected)
1099+
self.assertEquals(result.name, 'a')
1100+
1101+
result = df['routine1','result1']
1102+
expected = df['routine1','result1','']
1103+
assert_series_equal(result, expected)
1104+
self.assertEquals(result.name, ('routine1', 'result1'))
1105+
1106+
def test_mixed_depth_insert(self):
1107+
arrays = [[ 'a', 'top', 'top', 'routine1', 'routine1', 'routine2'],
1108+
[ '', 'OD', 'OD', 'result1', 'result2', 'result1'],
1109+
[ '', 'wx', 'wy', '', '', '']]
1110+
1111+
tuples = zip(*arrays)
1112+
tuples.sort()
1113+
index = MultiIndex.from_tuples(tuples)
1114+
df = DataFrame(randn(4,6),columns = index)
1115+
1116+
result = df.copy()
1117+
expected = df.copy()
1118+
result['b'] = [1,2,3,4]
1119+
expected['b','',''] = [1,2,3,4]
1120+
assert_frame_equal(result, expected)
1121+
1122+
def test_mixed_depth_drop(self):
1123+
arrays = [[ 'a', 'top', 'top', 'routine1', 'routine1', 'routine2'],
1124+
[ '', 'OD', 'OD', 'result1', 'result2', 'result1'],
1125+
[ '', 'wx', 'wy', '', '', '']]
1126+
1127+
tuples = zip(*arrays)
1128+
tuples.sort()
1129+
index = MultiIndex.from_tuples(tuples)
1130+
df = DataFrame(randn(4,6),columns = index)
1131+
1132+
result = df.drop('a',axis=1)
1133+
expected = df.drop([('a','','')],axis=1)
1134+
assert_frame_equal(expected, result)
1135+
1136+
result = df.drop(['top'],axis=1)
1137+
expected = df.drop([('top','OD','wx')], axis=1)
1138+
expected = expected.drop([('top','OD','wy')], axis=1)
1139+
assert_frame_equal(expected, result)
1140+
1141+
def test_mixed_depth_pop(self):
1142+
arrays = [[ 'a', 'top', 'top', 'routine1', 'routine1', 'routine2'],
1143+
[ '', 'OD', 'OD', 'result1', 'result2', 'result1'],
1144+
[ '', 'wx', 'wy', '', '', '']]
1145+
1146+
tuples = zip(*arrays)
1147+
tuples.sort()
1148+
index = MultiIndex.from_tuples(tuples)
1149+
df = DataFrame(randn(4,6),columns = index)
1150+
1151+
df1 = df.copy()
1152+
df2 = df.copy()
1153+
result = df1.pop('a')
1154+
expected = df2.pop(('a','',''))
1155+
assert_series_equal(expected, result)
1156+
assert_frame_equal(df1, df2)
1157+
self.assertEquals(result.name,'a')
1158+
1159+
expected = df1['top']
1160+
df1 = df1.drop(['top'],axis=1)
1161+
result = df2.pop('top')
1162+
assert_frame_equal(expected, result)
1163+
assert_frame_equal(df1, df2)
1164+
1165+
10861166
if __name__ == '__main__':
10871167

10881168
# unittest.main()

0 commit comments

Comments
 (0)