Skip to content

Commit 06dba79

Browse files
committed
BUG: preserve matching index names in DataFrame.append via concat, Index.append close GH #980
1 parent 079aee8 commit 06dba79

File tree

4 files changed

+46
-17
lines changed

4 files changed

+46
-17
lines changed

pandas/core/common.py

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -294,6 +294,15 @@ def _need_upcast(values):
294294
return True
295295
return False
296296

297+
298+
299+
def _consensus_name_attr(objs):
300+
name = objs[0].name
301+
for obj in objs[1:]:
302+
if obj.name != name:
303+
return None
304+
return name
305+
297306
#-------------------------------------------------------------------------------
298307
# Lots of little utilities
299308

pandas/core/index.py

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -253,11 +253,19 @@ def append(self, other):
253253
-------
254254
appended : Index
255255
"""
256+
name = self.name
256257
if isinstance(other, (list, tuple)):
257258
to_concat = (self.values,) + tuple(other)
259+
for obj in other:
260+
if isinstance(obj, Index) and obj.name != name:
261+
name = None
262+
break
258263
else:
259264
to_concat = self.values, other.values
260-
return Index(np.concatenate(to_concat))
265+
if isinstance(other, Index) and other.name != name:
266+
name = None
267+
268+
return Index(np.concatenate(to_concat), name=name)
261269

262270
def take(self, *args, **kwargs):
263271
"""
@@ -2238,3 +2246,12 @@ def _sanitize_and_check(indexes):
22382246
return indexes, 'special'
22392247
else:
22402248
return indexes, 'array'
2249+
2250+
2251+
def _get_consensus_names(indexes):
2252+
consensus_name = indexes[0].names
2253+
for index in indexes[1:]:
2254+
if index.names != consensus_name:
2255+
consensus_name = [None] * index.nlevels
2256+
break
2257+
return consensus_name

pandas/tests/test_index.py

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -224,6 +224,19 @@ def test_append_multiple(self):
224224
result = index.append([])
225225
self.assert_(result.equals(index))
226226

227+
def test_append_empty_preserve_name(self):
228+
left = Index([], name='foo')
229+
right = Index([1, 2, 3], name='foo')
230+
231+
result = left.append(right)
232+
self.assert_(result.name == 'foo')
233+
234+
left = Index([], name='foo')
235+
right = Index([1, 2, 3], name='bar')
236+
237+
result = left.append(right)
238+
self.assert_(result.name is None)
239+
227240
def test_add_string(self):
228241
# from bug report
229242
index = Index(['a', 'b', 'c'])
@@ -1470,3 +1483,5 @@ def test_get_combined_index():
14701483
nose.runmodule(argv=[__file__,'-vvs','-x','--pdb', '--pdb-failure'],
14711484
# '--with-coverage', '--cover-package=pandas.core'],
14721485
exit=False)
1486+
1487+

pandas/tools/merge.py

Lines changed: 4 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
from pandas.core.groupby import get_group_index
1010
from pandas.core.series import Series
1111
from pandas.core.index import (Factor, Index, MultiIndex, _get_combined_index,
12-
_ensure_index)
12+
_ensure_index, _get_consensus_names)
1313
from pandas.core.internals import (IntBlock, BoolBlock, BlockManager,
1414
make_block, _consolidate)
1515
from pandas.util.decorators import cache_readonly, Appender, Substitution
@@ -751,7 +751,7 @@ def __init__(self, objs, axis=0, join='outer', join_axes=None,
751751
def get_result(self):
752752
if self._is_series and self.axis == 0:
753753
new_data = np.concatenate([x.values for x in self.objs])
754-
name = _consensus_name_attr(self.objs)
754+
name = com._consensus_name_attr(self.objs)
755755
return Series(new_data, index=self.new_axes[0], name=name)
756756
elif self._is_series:
757757
data = dict(zip(self.new_axes[1], self.objs))
@@ -1031,32 +1031,20 @@ def _make_concat_multiindex(indexes, keys, levels=None, names=None):
10311031

10321032
return MultiIndex(levels=new_levels, labels=new_labels, names=new_names)
10331033

1034-
def _get_consensus_names(indexes):
1035-
consensus_name = indexes[0].names
1036-
for index in indexes[1:]:
1037-
if index.names != consensus_name:
1038-
consensus_name = [None] * index.nlevels
1039-
break
1040-
return consensus_name
1041-
1042-
def _consensus_name_attr(objs):
1043-
name = objs[0].name
1044-
for obj in objs[1:]:
1045-
if obj.name != name:
1046-
return None
1047-
return name
10481034

10491035
def _should_fill(lname, rname):
10501036
if not isinstance(lname, basestring) or not isinstance(rname, basestring):
10511037
return True
10521038
return lname == rname
10531039

1040+
10541041
def _all_indexes_same(indexes):
10551042
first = indexes[0]
10561043
for index in indexes[1:]:
10571044
if not first.equals(index):
10581045
return False
10591046
return True
10601047

1048+
10611049
def _any(x):
10621050
return x is not None and len(x) > 0 and any([y is not None for y in x])

0 commit comments

Comments
 (0)