diff --git a/doc/source/whatsnew/v0.24.0.txt b/doc/source/whatsnew/v0.24.0.txt index fc7019c486d9a..f53e270b18f97 100644 --- a/doc/source/whatsnew/v0.24.0.txt +++ b/doc/source/whatsnew/v0.24.0.txt @@ -1060,6 +1060,7 @@ Performance Improvements - Improved the performance of :func:`pandas.get_dummies` with ``sparse=True`` (:issue:`21997`) - Improved performance of :func:`IndexEngine.get_indexer_non_unique` for sorted, non-unique indexes (:issue:`9466`) - Improved performance of :func:`PeriodIndex.unique` (:issue:`23083`) +- Improved performance of :func:`pd.concat` for `Series` objects (:issue:`23404`) .. _whatsnew_0240.docs: diff --git a/pandas/core/generic.py b/pandas/core/generic.py index db10494f0724d..6ca8f6731bbb8 100644 --- a/pandas/core/generic.py +++ b/pandas/core/generic.py @@ -358,41 +358,44 @@ def _from_axes(cls, data, axes, **kwargs): d.update(kwargs) return cls(data, **d) - def _get_axis_number(self, axis): - axis = self._AXIS_ALIASES.get(axis, axis) + @classmethod + def _get_axis_number(cls, axis): + axis = cls._AXIS_ALIASES.get(axis, axis) if is_integer(axis): - if axis in self._AXIS_NAMES: + if axis in cls._AXIS_NAMES: return axis else: try: - return self._AXIS_NUMBERS[axis] + return cls._AXIS_NUMBERS[axis] except KeyError: pass raise ValueError('No axis named {0} for object type {1}' - .format(axis, type(self))) + .format(axis, type(cls))) - def _get_axis_name(self, axis): - axis = self._AXIS_ALIASES.get(axis, axis) + @classmethod + def _get_axis_name(cls, axis): + axis = cls._AXIS_ALIASES.get(axis, axis) if isinstance(axis, string_types): - if axis in self._AXIS_NUMBERS: + if axis in cls._AXIS_NUMBERS: return axis else: try: - return self._AXIS_NAMES[axis] + return cls._AXIS_NAMES[axis] except KeyError: pass raise ValueError('No axis named {0} for object type {1}' - .format(axis, type(self))) + .format(axis, type(cls))) def _get_axis(self, axis): name = self._get_axis_name(axis) return getattr(self, name) - def _get_block_manager_axis(self, axis): + @classmethod + def _get_block_manager_axis(cls, axis): """Map the axis to the block_manager axis.""" - axis = self._get_axis_number(axis) - if self._AXIS_REVERSED: - m = self._AXIS_LEN - 1 + axis = cls._get_axis_number(axis) + if cls._AXIS_REVERSED: + m = cls._AXIS_LEN - 1 return m - axis return axis diff --git a/pandas/core/reshape/concat.py b/pandas/core/reshape/concat.py index 9f8564541a936..0e60068732447 100644 --- a/pandas/core/reshape/concat.py +++ b/pandas/core/reshape/concat.py @@ -322,7 +322,7 @@ def __init__(self, objs, axis=0, join='outer', join_axes=None, # Standardize axis parameter to int if isinstance(sample, Series): - axis = DataFrame()._get_axis_number(axis) + axis = DataFrame._get_axis_number(axis) else: axis = sample._get_axis_number(axis) diff --git a/pandas/tests/generic/test_generic.py b/pandas/tests/generic/test_generic.py index 1652835de8228..46bb6303d8908 100644 --- a/pandas/tests/generic/test_generic.py +++ b/pandas/tests/generic/test_generic.py @@ -1019,3 +1019,15 @@ def test_pipe_panel(self): with pytest.raises(ValueError): result = wp.pipe((f, 'y'), x=1, y=1) + + @pytest.mark.parametrize('box', [pd.Series, pd.DataFrame]) + def test_axis_classmethods(self, box): + obj = box() + values = (list(box._AXIS_NAMES.keys()) + + list(box._AXIS_NUMBERS.keys()) + + list(box._AXIS_ALIASES.keys())) + for v in values: + assert obj._get_axis_number(v) == box._get_axis_number(v) + assert obj._get_axis_name(v) == box._get_axis_name(v) + assert obj._get_block_manager_axis(v) == \ + box._get_block_manager_axis(v)