Skip to content

Commit 20a9e52

Browse files
jschendelPingviinituutti
authored andcommitted
CLN: Make repeat method consistent (pandas-dev#24395)
1 parent f5e8b56 commit 20a9e52

File tree

14 files changed

+157
-187
lines changed

14 files changed

+157
-187
lines changed

pandas/core/arrays/base.py

+39-13
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
from pandas.compat import PY3, set_function_name
1313
from pandas.compat.numpy import function as nv
1414
from pandas.errors import AbstractMethodError
15+
from pandas.util._decorators import Appender, Substitution
1516

1617
from pandas.core.dtypes.common import is_list_like
1718
from pandas.core.dtypes.generic import ABCIndexClass, ABCSeries
@@ -20,6 +21,8 @@
2021

2122
_not_implemented_message = "{} does not implement {}."
2223

24+
_extension_array_shared_docs = dict()
25+
2326

2427
class ExtensionArray(object):
2528
"""
@@ -580,32 +583,55 @@ def factorize(self, na_sentinel=-1):
580583
uniques = self._from_factorized(uniques, self)
581584
return labels, uniques
582585

583-
def repeat(self, repeats, axis=None):
584-
"""
585-
Repeat elements of an array.
586+
_extension_array_shared_docs['repeat'] = """
587+
Repeat elements of a %(klass)s.
586588
587-
.. versionadded:: 0.24.0
589+
Returns a new %(klass)s where each element of the current %(klass)s
590+
is repeated consecutively a given number of times.
588591
589592
Parameters
590593
----------
591-
repeats : int
592-
This should be a non-negative integer. Repeating 0 times
593-
will return an empty array.
594+
repeats : int or array of ints
595+
The number of repetitions for each element. This should be a
596+
non-negative integer. Repeating 0 times will return an empty
597+
%(klass)s.
598+
*args
599+
Additional arguments have no effect but might be accepted for
600+
compatibility with numpy.
601+
**kwargs
602+
Additional keywords have no effect but might be accepted for
603+
compatibility with numpy.
594604
595605
Returns
596606
-------
597-
repeated_array : ExtensionArray
598-
Same type as the input, with elements repeated `repeats` times.
607+
repeated_array : %(klass)s
608+
Newly created %(klass)s with repeated elements.
599609
600610
See Also
601611
--------
612+
Series.repeat : Equivalent function for Series.
613+
Index.repeat : Equivalent function for Index.
602614
numpy.repeat : Similar method for :class:`numpy.ndarray`.
603615
ExtensionArray.take : Take arbitrary positions.
616+
617+
Examples
618+
--------
619+
>>> cat = pd.Categorical(['a', 'b', 'c'])
620+
>>> cat
621+
[a, b, c]
622+
Categories (3, object): [a, b, c]
623+
>>> cat.repeat(2)
624+
[a, a, b, b, c, c]
625+
Categories (3, object): [a, b, c]
626+
>>> cat.repeat([1, 2, 3])
627+
[a, b, b, c, c, c]
628+
Categories (3, object): [a, b, c]
604629
"""
605-
if axis is not None:
606-
raise ValueError("'axis' must be None.")
607-
if repeats < 0:
608-
raise ValueError("negative repeats are not allowed.")
630+
631+
@Substitution(klass='ExtensionArray')
632+
@Appender(_extension_array_shared_docs['repeat'])
633+
def repeat(self, repeats, *args, **kwargs):
634+
nv.validate_repeat(args, kwargs)
609635
ind = np.arange(len(self)).repeat(repeats)
610636
return self.take(ind)
611637

pandas/core/arrays/categorical.py

+3-9
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@
3939
from pandas.io.formats import console
4040
from pandas.io.formats.terminal import get_terminal_size
4141

42-
from .base import ExtensionArray
42+
from .base import ExtensionArray, _extension_array_shared_docs
4343

4444
_take_msg = textwrap.dedent("""\
4545
Interpreting negative values in 'indexer' as missing values.
@@ -2394,15 +2394,9 @@ def describe(self):
23942394

23952395
return result
23962396

2397+
@Substitution(klass='Categorical')
2398+
@Appender(_extension_array_shared_docs['repeat'])
23972399
def repeat(self, repeats, *args, **kwargs):
2398-
"""
2399-
Repeat elements of a Categorical.
2400-
2401-
See Also
2402-
--------
2403-
numpy.ndarray.repeat
2404-
2405-
"""
24062400
nv.validate_repeat(args, kwargs)
24072401
codes = self._codes.repeat(repeats)
24082402
return self._constructor(values=codes, dtype=self.dtype, fastpath=True)

pandas/core/arrays/interval.py

+8-31
Original file line numberDiff line numberDiff line change
@@ -20,12 +20,13 @@
2020
ABCDatetimeIndex, ABCInterval, ABCIntervalIndex, ABCPeriodIndex, ABCSeries)
2121
from pandas.core.dtypes.missing import isna, notna
2222

23+
from pandas.core.arrays.base import (
24+
ExtensionArray, _extension_array_shared_docs)
25+
from pandas.core.arrays.categorical import Categorical
2326
import pandas.core.common as com
2427
from pandas.core.config import get_option
2528
from pandas.core.indexes.base import Index, ensure_index
2629

27-
from . import Categorical, ExtensionArray
28-
2930
_VALID_CLOSED = {'left', 'right', 'both', 'neither'}
3031
_interval_shared_docs = {}
3132

@@ -1000,35 +1001,11 @@ def to_tuples(self, na_tuple=True):
10001001
tuples = np.where(~self.isna(), tuples, np.nan)
10011002
return tuples
10021003

1003-
def repeat(self, repeats, **kwargs):
1004-
"""
1005-
Repeat elements of an IntervalArray.
1006-
1007-
Returns a new IntervalArray where each element of the current
1008-
IntervalArray is repeated consecutively a given number of times.
1009-
1010-
Parameters
1011-
----------
1012-
repeats : int
1013-
The number of repetitions for each element.
1014-
1015-
**kwargs
1016-
Additional keywords have no effect but might be accepted for
1017-
compatibility with numpy.
1018-
1019-
Returns
1020-
-------
1021-
IntervalArray
1022-
Newly created IntervalArray with repeated elements.
1023-
1024-
See Also
1025-
--------
1026-
Index.repeat : Equivalent function for Index.
1027-
Series.repeat : Equivalent function for Series.
1028-
numpy.repeat : Underlying implementation.
1029-
"""
1030-
left_repeat = self.left.repeat(repeats, **kwargs)
1031-
right_repeat = self.right.repeat(repeats, **kwargs)
1004+
@Appender(_extension_array_shared_docs['repeat'] % _shared_docs_kwargs)
1005+
def repeat(self, repeats, *args, **kwargs):
1006+
nv.validate_repeat(args, kwargs)
1007+
left_repeat = self.left.repeat(repeats)
1008+
right_repeat = self.right.repeat(repeats)
10321009
return self._shallow_copy(left=left_repeat, right=right_repeat)
10331010

10341011
_interval_shared_docs['overlaps'] = """

pandas/core/arrays/period.py

-14
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,6 @@
1111
period_asfreq_arr)
1212
from pandas._libs.tslibs.timedeltas import Timedelta, delta_to_nanoseconds
1313
import pandas.compat as compat
14-
from pandas.compat.numpy import function as nv
1514
from pandas.util._decorators import Appender, cache_readonly
1615
from pandas.util._validators import validate_fillna_kwargs
1716

@@ -593,19 +592,6 @@ def _format_native_types(self, na_rep=u'NaT', date_format=None, **kwargs):
593592

594593
# ------------------------------------------------------------------
595594

596-
def repeat(self, repeats, *args, **kwargs):
597-
"""
598-
Repeat elements of a PeriodArray.
599-
600-
See Also
601-
--------
602-
numpy.ndarray.repeat
603-
"""
604-
# TODO(DatetimeArray): remove
605-
nv.validate_repeat(args, kwargs)
606-
values = self._data.repeat(repeats)
607-
return type(self)(values, self.freq)
608-
609595
def astype(self, dtype, copy=True):
610596
# TODO: Figure out something better here...
611597
# We have DatetimeLikeArrayMixin ->

pandas/core/indexes/base.py

+21-14
Original file line numberDiff line numberDiff line change
@@ -834,41 +834,48 @@ def _assert_take_fillable(self, values, indices, allow_fill=True,
834834
taken = values.take(indices)
835835
return taken
836836

837-
def repeat(self, repeats, *args, **kwargs):
838-
"""
839-
Repeat elements of an Index.
837+
_index_shared_docs['repeat'] = """
838+
Repeat elements of a %(klass)s.
840839
841-
Returns a new index where each element of the current index
840+
Returns a new %(klass)s where each element of the current %(klass)s
842841
is repeated consecutively a given number of times.
843842
844843
Parameters
845844
----------
846-
repeats : int
847-
The number of repetitions for each element.
845+
repeats : int or array of ints
846+
The number of repetitions for each element. This should be a
847+
non-negative integer. Repeating 0 times will return an empty
848+
%(klass)s.
849+
*args
850+
Additional arguments have no effect but might be accepted for
851+
compatibility with numpy.
848852
**kwargs
849853
Additional keywords have no effect but might be accepted for
850854
compatibility with numpy.
851855
852856
Returns
853857
-------
854-
pandas.Index
855-
Newly created Index with repeated elements.
858+
repeated_index : %(klass)s
859+
Newly created %(klass)s with repeated elements.
856860
857861
See Also
858862
--------
859863
Series.repeat : Equivalent function for Series.
860-
numpy.repeat : Underlying implementation.
864+
numpy.repeat : Similar method for :class:`numpy.ndarray`.
861865
862866
Examples
863867
--------
864-
>>> idx = pd.Index([1, 2, 3])
868+
>>> idx = pd.Index(['a', 'b', 'c'])
865869
>>> idx
866-
Int64Index([1, 2, 3], dtype='int64')
870+
Index(['a', 'b', 'c'], dtype='object')
867871
>>> idx.repeat(2)
868-
Int64Index([1, 1, 2, 2, 3, 3], dtype='int64')
869-
>>> idx.repeat(3)
870-
Int64Index([1, 1, 1, 2, 2, 2, 3, 3, 3], dtype='int64')
872+
Index(['a', 'a', 'b', 'b', 'c', 'c'], dtype='object')
873+
>>> idx.repeat([1, 2, 3])
874+
Index(['a', 'b', 'b', 'c', 'c', 'c'], dtype='object')
871875
"""
876+
877+
@Appender(_index_shared_docs['repeat'] % _index_doc_kwargs)
878+
def repeat(self, repeats, *args, **kwargs):
872879
nv.validate_repeat(args, kwargs)
873880
return self._shallow_copy(self._values.repeat(repeats))
874881

pandas/core/indexes/datetimelike.py

+3-9
Original file line numberDiff line numberDiff line change
@@ -450,17 +450,11 @@ def isin(self, values):
450450

451451
return algorithms.isin(self.asi8, values.asi8)
452452

453+
@Appender(_index_shared_docs['repeat'] % _index_doc_kwargs)
453454
def repeat(self, repeats, *args, **kwargs):
454-
"""
455-
Analogous to ndarray.repeat.
456-
"""
457455
nv.validate_repeat(args, kwargs)
458-
if is_period_dtype(self):
459-
freq = self.freq
460-
else:
461-
freq = None
462-
return self._shallow_copy(self.asi8.repeat(repeats),
463-
freq=freq)
456+
freq = self.freq if is_period_dtype(self) else None
457+
return self._shallow_copy(self.asi8.repeat(repeats), freq=freq)
464458

465459
@Appender(_index_shared_docs['where'] % _index_doc_kwargs)
466460
def where(self, cond, other=None):

pandas/core/indexes/multi.py

+1
Original file line numberDiff line numberDiff line change
@@ -1857,6 +1857,7 @@ def append(self, other):
18571857
def argsort(self, *args, **kwargs):
18581858
return self.values.argsort(*args, **kwargs)
18591859

1860+
@Appender(_index_shared_docs['repeat'] % _index_doc_kwargs)
18601861
def repeat(self, repeats, *args, **kwargs):
18611862
nv.validate_repeat(args, kwargs)
18621863
return MultiIndex(levels=self.levels,

pandas/core/indexes/period.py

-4
Original file line numberDiff line numberDiff line change
@@ -924,10 +924,6 @@ def wrapper(self, other):
924924
wrapper.__name__ = '__{}__'.format(op.__name__)
925925
return wrapper
926926

927-
def repeat(self, repeats, *args, **kwargs):
928-
# TODO(DatetimeArray): Just use Index.repeat
929-
return Index.repeat(self, repeats, *args, **kwargs)
930-
931927
def view(self, dtype=None, type=None):
932928
# TODO(DatetimeArray): remove
933929
if dtype is None or dtype is __builtins__['type'](self):

pandas/core/series.py

+49-3
Original file line numberDiff line numberDiff line change
@@ -1038,12 +1038,58 @@ def _set_values(self, key, value):
10381038

10391039
def repeat(self, repeats, *args, **kwargs):
10401040
"""
1041-
Repeat elements of an Series. Refer to `numpy.ndarray.repeat`
1042-
for more information about the `repeats` argument.
1041+
Repeat elements of a Series.
1042+
1043+
Returns a new Series where each element of the current Series
1044+
is repeated consecutively a given number of times.
1045+
1046+
Parameters
1047+
----------
1048+
repeats : int or array of ints
1049+
The number of repetitions for each element. This should be a
1050+
non-negative integer. Repeating 0 times will return an empty
1051+
Series.
1052+
*args
1053+
Additional arguments have no effect but might be accepted for
1054+
compatibility with numpy.
1055+
**kwargs
1056+
Additional keywords have no effect but might be accepted for
1057+
compatibility with numpy.
1058+
1059+
Returns
1060+
-------
1061+
repeated_series : Series
1062+
Newly created Series with repeated elements.
10431063
10441064
See Also
10451065
--------
1046-
numpy.ndarray.repeat
1066+
Index.repeat : Equivalent function for Index.
1067+
numpy.repeat : Similar method for :class:`numpy.ndarray`.
1068+
1069+
Examples
1070+
--------
1071+
>>> s = pd.Series(['a', 'b', 'c'])
1072+
>>> s
1073+
0 a
1074+
1 b
1075+
2 c
1076+
dtype: object
1077+
>>> s.repeat(2)
1078+
0 a
1079+
0 a
1080+
1 b
1081+
1 b
1082+
2 c
1083+
2 c
1084+
dtype: object
1085+
>>> s.repeat([1, 2, 3])
1086+
0 a
1087+
1 b
1088+
1 b
1089+
2 c
1090+
2 c
1091+
2 c
1092+
dtype: object
10471093
"""
10481094
nv.validate_repeat(args, kwargs)
10491095
new_index = self.index.repeat(repeats)

pandas/tests/arrays/categorical/test_analytics.py

-16
Original file line numberDiff line numberDiff line change
@@ -295,22 +295,6 @@ def test_validate_inplace(self):
295295
with pytest.raises(ValueError):
296296
cat.sort_values(inplace=value)
297297

298-
def test_repeat(self):
299-
# GH10183
300-
cat = Categorical(["a", "b"], categories=["a", "b"])
301-
exp = Categorical(["a", "a", "b", "b"], categories=["a", "b"])
302-
res = cat.repeat(2)
303-
tm.assert_categorical_equal(res, exp)
304-
305-
def test_numpy_repeat(self):
306-
cat = Categorical(["a", "b"], categories=["a", "b"])
307-
exp = Categorical(["a", "a", "b", "b"], categories=["a", "b"])
308-
tm.assert_categorical_equal(np.repeat(cat, 2), exp)
309-
310-
msg = "the 'axis' parameter is not supported"
311-
with pytest.raises(ValueError, match=msg):
312-
np.repeat(cat, 2, axis=1)
313-
314298
def test_isna(self):
315299
exp = np.array([False, False, True])
316300
c = Categorical(["a", "b", np.nan])

0 commit comments

Comments
 (0)