pydata/pandas — pull request #4039 by jtratner (2013-06-26 01:22:53+00:00)
Title: BUG: Fix names handling in MultiIndex

MultiIndex handling of names is a bit inconsistent

```python
major_axis = Index(['foo', 'bar', 'baz', 'qux'])
minor_axis = Index(['one', 'two'])

major_labels = np.array([0, 0, 1, 2, 3, 3])
minor_labels = np.array([0, 1, 0, 1, 0, 1])
index_names = ['first', 'second']

# add extra name, fails
idx = MultiIndex(levels=[major_axis, minor_axis],
labels=[major_labels, minor_labels],
names=list("abc"))

# succeeds
idx = MultiIndex(levels=[major_axis, minor_axis],
labels=[major_labels, minor_labels],
names=index_names )

# but allows you to *set* names, allows extra
idx.names = list("abcdef")
```

This tries to address that, the problem is that it also makes some of the tests in `diff` fail. I'm not clear on *why* some of the tests are the way they are. (opened this pull request so that you can see the actual code changes):

Here's test_diff from tests/test_index

```python
def test_diff(self):
first = self.index
result = first - self.index[-3:]
expected = MultiIndex.from_tuples(sorted(self.index[:-3].values),
sortorder=0,
names=self.index.names)

# names not the same
chunklet = self.index[-3:]
chunklet.names = ['foo', 'baz']
result = first - chunklet
self.assertEqual(result.names, [None, None])

# name from non-empty array
result = first.diff([('foo', 'one')])
expected = pd.MultiIndex.from_tuples([('bar', 'one'), ('baz', 'two'), ('foo', 'two'),
('qux', 'one'), ('qux', 'two')])
expected.names = first.names
self.assertEqual(first.names, result.names)
```

In `diff`, it looks like the names *should* actually stay the same if the other is a set of tuples
```python
def diff(self, other):
"""
Compute sorted set difference of two MultiIndex objects

Returns
-------
diff : MultiIndex
"""
self._assert_can_do_setop(other)

if not isinstance(other, MultiIndex):
if len(other) == 0:
return self
try:
other = MultiIndex.from_tuples(other)
except:
raise TypeError("other should be a MultiIndex or a list of tuples")
# APPEARS TO SET NAME AS SELF.NAMES
result_names = self.names
else:
result_names = self.names if self.names == other.names else None
```

Any thoughts on this? Maybe I'm just not understanding how MultiIndexes work.