Skip to content

Commit d79bf0e

Browse files
committed
ENH: Add optional argument keep_index to dataframe melt method
Setting keep_index to True will reuse the original DataFrame index + names of melted columns as additional level. closes issue pandas-dev#17440
1 parent 20fee85 commit d79bf0e

File tree

2 files changed

+25
-7
lines changed

2 files changed

+25
-7
lines changed

pandas/core/frame.py

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4367,6 +4367,10 @@ def unstack(self, level=-1, fill_value=None):
43674367
Name to use for the 'value' column.
43684368
col_level : int or string, optional
43694369
If columns are a MultiIndex then use this level to melt.
4370+
keep_index : boolean, optional, default False
4371+
If True, the original index is reused.
4372+
In the resulting MulitIndex the names of the unpivoted columns
4373+
are added as an additional level to ensure uniqueness.
43704374
43714375
See also
43724376
--------
@@ -4439,11 +4443,11 @@ def unstack(self, level=-1, fill_value=None):
44394443
versionadded='.. versionadded:: 0.20.0\n',
44404444
other='melt'))
44414445
def melt(self, id_vars=None, value_vars=None, var_name=None,
4442-
value_name='value', col_level=None):
4446+
value_name='value', col_level=None, keep_index=False):
44434447
from pandas.core.reshape.reshape import melt
44444448
return melt(self, id_vars=id_vars, value_vars=value_vars,
44454449
var_name=var_name, value_name=value_name,
4446-
col_level=col_level)
4450+
col_level=col_level, keep_index=keep_index)
44474451

44484452
# ----------------------------------------------------------------------
44494453
# Time series-related

pandas/core/reshape/reshape.py

Lines changed: 19 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -720,8 +720,7 @@ def _convert_level_number(level_num, columns):
720720
versionadded="",
721721
other='DataFrame.melt'))
722722
def melt(frame, id_vars=None, value_vars=None, var_name=None,
723-
value_name='value', col_level=None):
724-
# TODO: what about the existing index?
723+
value_name='value', col_level=None, keep_index=False):
725724
if id_vars is not None:
726725
if not is_list_like(id_vars):
727726
id_vars = [id_vars]
@@ -778,9 +777,24 @@ def melt(frame, id_vars=None, value_vars=None, var_name=None,
778777
# asanyarray will keep the columns as an Index
779778
mdata[col] = np.asanyarray(frame.columns
780779
._get_level_values(i)).repeat(N)
781-
782-
return DataFrame(mdata, columns=mcolumns)
783-
780+
781+
result = DataFrame(mdata, columns=mcolumns)
782+
783+
if keep_index:
784+
orig_index_values = list(np.tile(frame.index.get_values(),K))
785+
786+
if len(frame.index.names) == len(set(frame.index.names)):
787+
orig_index_names = frame.index.names
788+
else:
789+
orig_index_names = ["original_index_{i}".format(i=i)
790+
for i in range(len(frame.index.names))]
791+
792+
result[orig_index_names] = DataFrame(orig_index_values)
793+
794+
result = result.set_index(orig_index_names + list(var_name))
795+
796+
return result
797+
784798

785799
def lreshape(data, groups, dropna=True, label=None):
786800
"""

0 commit comments

Comments
 (0)