Skip to content

Commit 5955804

Browse files
Dr-Irvjreback
authored andcommitted
BUG: GH #12223, GH #15262. Allow ints for names in MultiIndex
closes #12223 closes #15262 Author: Dr-Irv <[email protected]> Closes #15478 from Dr-Irv/Issue15262 and squashes the following commits: 15d8433 [Dr-Irv] Address jreback comments 10667a3 [Dr-Irv] Fix types for test 8935068 [Dr-Irv] resolve conflicts 385ca3e [Dr-Irv] BUG: GH #12223, GH #15262. Allow ints for names in MultiIndex
1 parent 7e0a71b commit 5955804

File tree

10 files changed

+46
-22
lines changed

10 files changed

+46
-22
lines changed

doc/source/whatsnew/v0.20.0.txt

+1
Original file line numberDiff line numberDiff line change
@@ -550,6 +550,7 @@ Bug Fixes
550550

551551
- Bug in ``Series.where()`` and ``DataFrame.where()`` where array-like conditionals were being rejected (:issue:`15414`)
552552
- Bug in ``Series`` construction with a datetimetz (:issue:`14928`)
553+
- Bug in output formatting of a ``MultiIndex`` when names are integers (:issue:`12223`, :issue:`15262`)
553554

554555
- Bug in compat for passing long integers to ``Timestamp.replace`` (:issue:`15030`)
555556
- Bug in ``.loc`` that would not return the correct dtype for scalar access for a DataFrame (:issue:`11617`)

pandas/core/frame.py

+3-3
Original file line numberDiff line numberDiff line change
@@ -2876,7 +2876,7 @@ def set_index(self, keys, drop=True, append=False, inplace=False,
28762876
names = [x for x in self.index.names]
28772877
if isinstance(self.index, MultiIndex):
28782878
for i in range(self.index.nlevels):
2879-
arrays.append(self.index.get_level_values(i))
2879+
arrays.append(self.index._get_level_values(i))
28802880
else:
28812881
arrays.append(self.index)
28822882

@@ -2886,9 +2886,9 @@ def set_index(self, keys, drop=True, append=False, inplace=False,
28862886
# append all but the last column so we don't have to modify
28872887
# the end of this loop
28882888
for n in range(col.nlevels - 1):
2889-
arrays.append(col.get_level_values(n))
2889+
arrays.append(col._get_level_values(n))
28902890

2891-
level = col.get_level_values(col.nlevels - 1)
2891+
level = col._get_level_values(col.nlevels - 1)
28922892
names.extend(col.names)
28932893
elif isinstance(col, Series):
28942894
level = col._values

pandas/core/groupby.py

+3-3
Original file line numberDiff line numberDiff line change
@@ -291,8 +291,8 @@ def _set_grouper(self, obj, sort=False):
291291
# equivalent to the axis name
292292
if isinstance(ax, MultiIndex):
293293
level = ax._get_level_number(level)
294-
ax = Index(ax.get_level_values(
295-
level), name=ax.names[level])
294+
ax = Index(ax._get_level_values(level),
295+
name=ax.names[level])
296296

297297
else:
298298
if level not in (0, ax.name):
@@ -761,7 +761,7 @@ def _index_with_as_index(self, b):
761761
gp = self.grouper
762762
levels = chain((gp.levels[i][gp.labels[i][b]]
763763
for i in range(len(gp.groupings))),
764-
(original.get_level_values(i)[b]
764+
(original._get_level_values(i)[b]
765765
for i in range(original.nlevels)))
766766
new = MultiIndex.from_arrays(list(levels))
767767
new.names = gp.names + original.names

pandas/core/reshape.py

+2-1
Original file line numberDiff line numberDiff line change
@@ -811,7 +811,8 @@ def melt(frame, id_vars=None, value_vars=None, var_name=None,
811811
mdata[value_name] = frame.values.ravel('F')
812812
for i, col in enumerate(var_name):
813813
# asanyarray will keep the columns as an Index
814-
mdata[col] = np.asanyarray(frame.columns.get_level_values(i)).repeat(N)
814+
mdata[col] = np.asanyarray(frame.columns
815+
._get_level_values(i)).repeat(N)
815816

816817
return DataFrame(mdata, columns=mcolumns)
817818

pandas/formats/format.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -1566,7 +1566,7 @@ def _save_header(self):
15661566
if isinstance(index_label, list) and len(index_label) > 1:
15671567
col_line.extend([''] * (len(index_label) - 1))
15681568

1569-
col_line.extend(columns.get_level_values(i))
1569+
col_line.extend(columns._get_level_values(i))
15701570

15711571
writer.writerow(col_line)
15721572

pandas/indexes/base.py

+6-4
Original file line numberDiff line numberDiff line change
@@ -2334,9 +2334,9 @@ def set_value(self, arr, key, value):
23342334
self._engine.set_value(_values_from_object(arr),
23352335
_values_from_object(key), value)
23362336

2337-
def get_level_values(self, level):
2337+
def _get_level_values(self, level):
23382338
"""
2339-
Return vector of label values for requested level, equal to the length
2339+
Return an Index of values for requested level, equal to the length
23402340
of the index
23412341
23422342
Parameters
@@ -2345,12 +2345,14 @@ def get_level_values(self, level):
23452345
23462346
Returns
23472347
-------
2348-
values : ndarray
2348+
values : Index
23492349
"""
2350-
# checks that level number is actually just 1
2350+
23512351
self._validate_index_level(level)
23522352
return self
23532353

2354+
get_level_values = _get_level_values
2355+
23542356
_index_shared_docs['get_indexer'] = """
23552357
Compute indexer and mask for new index given the current index. The
23562358
indexer should be then used as an input to ndarray.take to align the

pandas/indexes/multi.py

+8-6
Original file line numberDiff line numberDiff line change
@@ -684,7 +684,7 @@ def is_monotonic_increasing(self):
684684
"""
685685

686686
# reversed() because lexsort() wants the most significant key last.
687-
values = [self._get_level_values(i)
687+
values = [self._get_level_values(i).values
688688
for i in reversed(range(len(self.levels)))]
689689
try:
690690
sort_order = np.lexsort(values)
@@ -866,7 +866,8 @@ def _get_level_values(self, level):
866866
labels = self.labels[level]
867867
filled = algos.take_1d(unique._values, labels,
868868
fill_value=unique._na_value)
869-
return filled
869+
values = unique._shallow_copy(filled)
870+
return values
870871

871872
def get_level_values(self, level):
872873
"""
@@ -883,7 +884,7 @@ def get_level_values(self, level):
883884
"""
884885
level = self._get_level_number(level)
885886
values = self._get_level_values(level)
886-
return self.levels[level]._shallow_copy(values)
887+
return values
887888

888889
def format(self, space=2, sparsify=None, adjoin=True, names=False,
889890
na_rep=None, formatter=None):
@@ -966,7 +967,8 @@ def to_frame(self, index=True):
966967
"""
967968

968969
from pandas import DataFrame
969-
result = DataFrame({(name or level): self.get_level_values(level)
970+
result = DataFrame({(name or level):
971+
self._get_level_values(level)
970972
for name, level in
971973
zip(self.names, range(len(self.levels)))},
972974
copy=False)
@@ -1301,8 +1303,8 @@ def append(self, other):
13011303
for o in other):
13021304
arrays = []
13031305
for i in range(self.nlevels):
1304-
label = self.get_level_values(i)
1305-
appended = [o.get_level_values(i) for o in other]
1306+
label = self._get_level_values(i)
1307+
appended = [o._get_level_values(i) for o in other]
13061308
arrays.append(label.append(appended))
13071309
return MultiIndex.from_arrays(arrays, names=self.names)
13081310

pandas/io/sql.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -749,7 +749,7 @@ def _get_column_names_and_types(self, dtype_mapper):
749749
if self.index is not None:
750750
for i, idx_label in enumerate(self.index):
751751
idx_type = dtype_mapper(
752-
self.frame.index.get_level_values(i))
752+
self.frame.index._get_level_values(i))
753753
column_names_and_types.append((text_type(idx_label),
754754
idx_type, True))
755755

pandas/tests/frame/test_combine_concat.py

+18
Original file line numberDiff line numberDiff line change
@@ -422,6 +422,24 @@ def test_concat_axis_parameter(self):
422422
with assertRaisesRegexp(ValueError, 'No axis named'):
423423
pd.concat([series1, series2], axis='something')
424424

425+
def test_concat_numerical_names(self):
426+
# #15262 # #12223
427+
df = pd.DataFrame({'col': range(9)},
428+
dtype='int32',
429+
index=(pd.MultiIndex
430+
.from_product([['A0', 'A1', 'A2'],
431+
['B0', 'B1', 'B2']],
432+
names=[1, 2])))
433+
result = pd.concat((df.iloc[:2, :], df.iloc[-2:, :]))
434+
expected = pd.DataFrame({'col': [0, 1, 7, 8]},
435+
dtype='int32',
436+
index=pd.MultiIndex.from_tuples([('A0', 'B0'),
437+
('A0', 'B1'),
438+
('A2', 'B1'),
439+
('A2', 'B2')],
440+
names=[1, 2]))
441+
tm.assert_frame_equal(result, expected)
442+
425443

426444
class TestDataFrameCombineFirst(tm.TestCase, TestData):
427445

pandas/util/doctools.py

+3-3
Original file line numberDiff line numberDiff line change
@@ -113,12 +113,12 @@ def _insert_index(self, data):
113113
else:
114114
for i in range(idx_nlevels):
115115
data.insert(i, 'Index{0}'.format(i),
116-
data.index.get_level_values(i))
116+
data.index._get_level_values(i))
117117

118118
col_nlevels = data.columns.nlevels
119119
if col_nlevels > 1:
120-
col = data.columns.get_level_values(0)
121-
values = [data.columns.get_level_values(i).values
120+
col = data.columns._get_level_values(0)
121+
values = [data.columns._get_level_values(i).values
122122
for i in range(1, col_nlevels)]
123123
col_df = pd.DataFrame(values)
124124
data.columns = col_df.columns

0 commit comments

Comments
 (0)