Skip to content

Commit 7597471

Browse files
committed
ENH: droplevel name/names fix, pivot correctly sets names now (nice)
1 parent b9b24bc commit 7597471

File tree

6 files changed

+37
-24
lines changed

6 files changed

+37
-24
lines changed

RELEASE.rst

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,13 @@ pandas 0.4.3
1010

1111
**Release date:** not yet released
1212

13+
**New features / modules**
14+
15+
- Add `name` attribute to standard Index so that stacking / unstacking does
16+
not discard names and so that indexed DataFrame objects can be reliably
17+
round-tripped to flat files, pickle, HDF5, etc.
18+
- Add `name` attribute to `Series` and added relevant logic and tests
19+
1320
**Improvements to existing features**
1421

1522
- Skip xlrd-related unit tests if not installed
@@ -22,7 +29,7 @@ pandas 0.4.3
2229
intersection. Implement `Int64Index.intersection`
2330
- `MultiIndex.sortlevel` discarded the level names (GH #202)
2431
- Fix bugs in groupby, join, and append due to improper concatenation of
25-
`MultiIndex` objets (GH #201)
32+
`MultiIndex` objects (GH #201)
2633
- Fix regression from 0.4.1, `isnull` and `notnull` ceased to work on other
2734
kinds of Python scalar objects like `datetime.datetime`
2835
- Raise more helpful exception when attempting to write empty DataFrame or

TODO.rst

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,6 @@
11
- SparseSeries name integration + tests
22
- Refactor Series.repr
3+
- .name pickling / unpicking / HDFStore handling
4+
- Is there a way to write hierarchical columns to csv?
5+
- Possible to blow away existing name when creating MultiIndex?
6+
- prettytable output with index names

pandas/core/index.py

Lines changed: 4 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -5,10 +5,9 @@
55

66
import numpy as np
77

8-
from pandas.core.common import (_format, adjoin as _adjoin, _stringify,
8+
from pandas.core.common import (adjoin as _adjoin, _stringify,
99
_is_bool_indexer, _asarray_tuplesafe)
1010
from pandas.util.decorators import deprecate, cache_readonly
11-
import pandas.core.common as common
1211
import pandas._tseries as lib
1312

1413
__all__ = ['Index']
@@ -820,9 +819,9 @@ def __init__(self, levels, labels, sortorder=None, names=None,
820819
assert(len(names) == self.nlevels)
821820
self.names = list(names)
822821

823-
# # set the name
824-
# for i, name in enumerate(self.names):
825-
# self.levels[i].name == name
822+
# set the name
823+
for i, name in enumerate(self.names):
824+
self.levels[i].name = name
826825

827826
if sortorder is not None:
828827
self.sortorder = int(sortorder)
@@ -1028,18 +1027,6 @@ def take(self, *args, **kwargs):
10281027
new_labels = [lab.take(*args, **kwargs) for lab in self.labels]
10291028
return MultiIndex(levels=self.levels, labels=new_labels)
10301029

1031-
def append(self, other):
1032-
"""
1033-
Append two MultiIndex objects
1034-
1035-
Parameters
1036-
----------
1037-
other : MultiIndex or list/tuple of MultiIndex objects
1038-
1039-
Returns
1040-
-------
1041-
appended : MultiIndex
1042-
"""
10431030
def append(self, other):
10441031
"""
10451032
Append a collection of Index options together

pandas/core/reshape.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -200,7 +200,8 @@ def pivot(self, index=None, columns=None, values=None):
200200
"""
201201
index_vals = self[index]
202202
column_vals = self[columns]
203-
mindex = MultiIndex.from_arrays([index_vals, column_vals])
203+
mindex = MultiIndex.from_arrays([index_vals, column_vals],
204+
names=[index, columns])
204205

205206
if values is None:
206207
items = self.columns - [index, columns]

pandas/tests/test_frame.py

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1524,18 +1524,18 @@ def test_to_csv_multiindex(self):
15241524

15251525
frame = self.frame
15261526
old_index = frame.index
1527-
new_index = MultiIndex.from_arrays(np.arange(len(old_index)*2).reshape(2,-1))
1527+
arrays = np.arange(len(old_index)*2).reshape(2,-1)
1528+
new_index = MultiIndex.from_arrays(arrays, names=['first', 'second'])
15281529
frame.index = new_index
15291530
frame.to_csv(path, header=False)
15301531
frame.to_csv(path, cols=['A', 'B'])
15311532

1532-
15331533
# round trip
15341534
frame.to_csv(path)
1535-
15361535
df = DataFrame.from_csv(path, index_col=[0,1])
15371536

15381537
assert_frame_equal(frame, df)
1538+
self.assertEqual(frame.index.names, df.index.names)
15391539
self.frame.index = old_index # needed if setUP becomes a classmethod
15401540

15411541
# try multiindex with dates
@@ -1965,6 +1965,15 @@ def test_pivot(self):
19651965

19661966
assert_frame_equal(pivoted, expected)
19671967

1968+
# name tracking
1969+
self.assertEqual(pivoted.index.name, 'index')
1970+
self.assertEqual(pivoted.columns.name, 'columns')
1971+
1972+
# don't specify values
1973+
pivoted = frame.pivot(index='index', columns='columns')
1974+
self.assertEqual(pivoted.index.name, 'index')
1975+
self.assertEqual(pivoted.columns.names, [None, 'columns'])
1976+
19681977
# pivot multiple columns
19691978
wp = tm.makePanel()
19701979
lp = wp.to_long()

pandas/tests/test_index.py

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -566,7 +566,8 @@ def setUp(self):
566566
minor_labels = np.array([0, 1, 0, 1, 0, 1])
567567

568568
self.index = MultiIndex(levels=[major_axis, minor_axis],
569-
labels=[major_labels, minor_labels])
569+
labels=[major_labels, minor_labels],
570+
names=['first', 'second'])
570571

571572
def test_constructor_single_level(self):
572573
single_level = MultiIndex(levels=[['foo', 'bar', 'baz', 'qux']],
@@ -603,7 +604,6 @@ def test_iter(self):
603604
self.assert_(result == expected)
604605

605606
def test_pickle(self):
606-
import pickle
607607
pickled = pickle.dumps(self.index)
608608
unpickled = pickle.loads(pickled)
609609
self.assert_(self.index.equals(unpickled))
@@ -945,6 +945,11 @@ def test_drop(self):
945945
expected = self.index[[2, 3, 5]]
946946
self.assert_(dropped.equals(expected))
947947

948+
def test_droplevel_with_names(self):
949+
index = self.index[self.index.get_loc('foo')]
950+
dropped = index.droplevel(0)
951+
self.assertEqual(dropped.name, 'second')
952+
948953
def test_insert(self):
949954
# key contained in all levels
950955
new_index = self.index.insert(0, ('bar', 'two'))

0 commit comments

Comments
 (0)