Coverage for /pythoncovmergedfiles/medio/medio/usr/local/lib/python3.11/site-packages/pandas/core/base.py: 40%
Shortcuts on this page
r m x toggle line displays
j k next/prev highlighted chunk
0 (zero) top of page
1 (one) first highlighted chunk
Shortcuts on this page
r m x toggle line displays
j k next/prev highlighted chunk
0 (zero) top of page
1 (one) first highlighted chunk
1"""
2Base and utility classes for pandas objects.
3"""
5from __future__ import annotations
7from typing import (
8 TYPE_CHECKING,
9 Any,
10 Generic,
11 Literal,
12 Self,
13 cast,
14 final,
15 overload,
16)
17import warnings
19import numpy as np
21from pandas._libs import lib
22from pandas._typing import (
23 AxisInt,
24 DtypeObj,
25 IndexLabel,
26 NDFrameT,
27 Shape,
28 npt,
29)
30from pandas.compat import PYPY
31from pandas.compat.numpy import function as nv
32from pandas.errors import (
33 AbstractMethodError,
34 Pandas4Warning,
35)
36from pandas.util._decorators import cache_readonly
37from pandas.util._exceptions import find_stack_level
39from pandas.core.dtypes.cast import (
40 can_hold_element,
41 maybe_unbox_numpy_scalar,
42)
43from pandas.core.dtypes.common import (
44 is_object_dtype,
45 is_scalar,
46)
47from pandas.core.dtypes.dtypes import ExtensionDtype
48from pandas.core.dtypes.generic import (
49 ABCDataFrame,
50 ABCIndex,
51 ABCMultiIndex,
52 ABCSeries,
53)
54from pandas.core.dtypes.missing import (
55 isna,
56 remove_na_arraylike,
57)
59from pandas.core import (
60 algorithms,
61 nanops,
62 ops,
63)
64from pandas.core.accessor import DirNamesMixin
65from pandas.core.arraylike import OpsMixin
66from pandas.core.arrays import ExtensionArray
67from pandas.core.construction import (
68 ensure_wrapped_if_datetimelike,
69 extract_array,
70)
72if TYPE_CHECKING:
73 from collections.abc import (
74 Hashable,
75 Iterator,
76 )
78 from pandas._typing import (
79 DropKeep,
80 NumpySorter,
81 NumpyValueArrayLike,
82 ScalarLike_co,
83 )
85 from pandas import (
86 DataFrame,
87 Index,
88 Series,
89 )
92class PandasObject(DirNamesMixin):
93 """
94 Base class for various pandas objects.
95 """
97 # results from calls to methods decorated with cache_readonly get added to _cache
98 _cache: dict[str, Any]
100 @property
101 def _constructor(self) -> type[Self]:
102 """
103 Class constructor (for this class it's just `__class__`).
104 """
105 return type(self)
107 def __repr__(self) -> str:
108 """
109 Return a string representation for a particular object.
110 """
111 # Should be overwritten by base classes
112 return object.__repr__(self)
114 def _reset_cache(self, key: str | None = None) -> None:
115 """
116 Reset cached properties. If ``key`` is passed, only clears that key.
117 """
118 if not hasattr(self, "_cache"):
119 return
120 if key is None:
121 self._cache.clear()
122 else:
123 self._cache.pop(key, None)
125 def __sizeof__(self) -> int:
126 """
127 Generates the total memory usage for an object that returns
128 either a value or Series of values
129 """
130 memory_usage = getattr(self, "memory_usage", None)
131 if memory_usage:
132 mem = memory_usage(deep=True)
133 return int(mem if is_scalar(mem) else mem.sum())
135 # no memory_usage attribute, so fall back to object's 'sizeof'
136 return super().__sizeof__()
139class NoNewAttributesMixin:
140 """
141 Mixin which prevents adding new attributes.
143 Prevents additional attributes via xxx.attribute = "something" after a
144 call to `self.__freeze()`. Mainly used to prevent the user from using
145 wrong attributes on an accessor (`Series.cat/.str/.dt`).
147 If you really want to add a new attribute at a later time, you need to use
148 `object.__setattr__(self, key, value)`.
149 """
151 def _freeze(self) -> None:
152 """
153 Prevents setting additional attributes.
154 """
155 object.__setattr__(self, "__frozen", True)
157 # prevent adding any attribute via s.xxx.new_attribute = ...
158 def __setattr__(self, key: str, value) -> None:
159 # _cache is used by a decorator
160 # We need to check both 1.) cls.__dict__ and 2.) getattr(self, key)
161 # because
162 # 1.) getattr is false for attributes that raise errors
163 # 2.) cls.__dict__ doesn't traverse into base classes
164 if getattr(self, "__frozen", False) and not (
165 key == "_cache"
166 or key in type(self).__dict__
167 or getattr(self, key, None) is not None
168 ):
169 raise AttributeError(f"You cannot add any new attribute '{key}'")
170 object.__setattr__(self, key, value)
173class SelectionMixin(Generic[NDFrameT]):
174 """
175 mixin implementing the selection & aggregation interface on a group-like
176 object sub-classes need to define: obj, exclusions
177 """
179 obj: NDFrameT
180 _selection: IndexLabel | None = None
181 exclusions: frozenset[Hashable]
182 _internal_names = ["_cache", "__setstate__"]
183 _internal_names_set = set(_internal_names)
185 @final
186 @property
187 def _selection_list(self):
188 if not isinstance(
189 self._selection, (list, tuple, ABCSeries, ABCIndex, np.ndarray)
190 ):
191 return [self._selection]
192 return self._selection
194 @cache_readonly
195 def _selected_obj(self):
196 if self._selection is None or isinstance(self.obj, ABCSeries):
197 return self.obj
198 else:
199 return self.obj[self._selection]
201 @final
202 @cache_readonly
203 def ndim(self) -> int:
204 return self._selected_obj.ndim
206 @final
207 @cache_readonly
208 def _obj_with_exclusions(self):
209 if isinstance(self.obj, ABCSeries):
210 return self.obj
212 if self._selection is not None:
213 return self.obj[self._selection_list]
215 if len(self.exclusions) > 0:
216 return self.obj._drop_axis(self.exclusions, axis=1)
217 else:
218 return self.obj
220 def __getitem__(self, key):
221 if self._selection is not None:
222 raise IndexError(f"Column(s) {self._selection} already selected")
224 if isinstance(key, tuple):
225 warnings.warn(
226 "Passing a tuple to __getitem__ is deprecated and "
227 "will raise a KeyError in a future version. Use a list instead.",
228 Pandas4Warning,
229 stacklevel=find_stack_level(),
230 )
231 key = list(key)
233 if isinstance(key, (list, ABCSeries, ABCIndex, np.ndarray)):
234 if len(self.obj.columns.intersection(key)) != len(set(key)):
235 bad_keys = list(set(key).difference(self.obj.columns))
236 raise KeyError(f"Columns not found: {str(bad_keys)[1:-1]}")
237 return self._gotitem(list(key), ndim=2)
239 else:
240 if key not in self.obj:
241 raise KeyError(f"Column not found: {key}")
242 ndim = self.obj[key].ndim
243 return self._gotitem(key, ndim=ndim)
245 def _gotitem(self, key, ndim: int, subset=None):
246 """
247 sub-classes to define
248 return a sliced object
250 Parameters
251 ----------
252 key : str / list of selections
253 ndim : {1, 2}
254 requested ndim of result
255 subset : object, default None
256 subset to act on
257 """
258 raise AbstractMethodError(self)
260 @final
261 def _infer_selection(self, key, subset: Series | DataFrame):
262 """
263 Infer the `selection` to pass to our constructor in _gotitem.
264 """
265 # Shared by Rolling and Resample
266 selection = None
267 if subset.ndim == 2 and (
268 (lib.is_scalar(key) and key in subset) or lib.is_list_like(key)
269 ):
270 selection = key
271 elif subset.ndim == 1 and lib.is_scalar(key) and key == subset.name:
272 selection = key
273 return selection
275 def aggregate(self, func, *args, **kwargs):
276 raise AbstractMethodError(self)
278 agg = aggregate
281class IndexOpsMixin(OpsMixin):
282 """
283 Common ops mixin to support a unified interface / docs for Series / Index
284 """
286 # ndarray compatibility
287 __array_priority__ = 1000
288 _hidden_attrs: frozenset[str] = frozenset(
289 ["tolist"] # tolist is not deprecated, just suppressed in the __dir__
290 )
292 @property
293 def dtype(self) -> DtypeObj:
294 # must be defined here as a property for mypy
295 raise AbstractMethodError(self)
297 @property
298 def _values(self) -> ExtensionArray | np.ndarray:
299 # must be defined here as a property for mypy
300 raise AbstractMethodError(self)
302 @final
303 def transpose(self, *args, **kwargs) -> Self:
304 """
305 Return the transpose, which is by definition self.
307 Returns
308 -------
309 %(klass)s
310 """
311 nv.validate_transpose(args, kwargs)
312 return self
314 T = property(
315 transpose,
316 doc="""
317 Return the transpose, which is by definition self.
319 For 1D objects (Series, Index) transposition has no effect; the
320 object is returned unchanged. Provided for API compatibility with
321 DataFrame and NumPy.
323 See Also
324 --------
325 Index : Immutable sequence used for indexing and alignment.
327 Examples
328 --------
329 For Series:
331 >>> s = pd.Series(['Ant', 'Bear', 'Cow'])
332 >>> s
333 0 Ant
334 1 Bear
335 2 Cow
336 dtype: str
337 >>> s.T
338 0 Ant
339 1 Bear
340 2 Cow
341 dtype: str
343 For Index:
345 >>> idx = pd.Index([1, 2, 3])
346 >>> idx.T
347 Index([1, 2, 3], dtype='int64')
348 """,
349 )
351 @property
352 def shape(self) -> Shape:
353 """
354 Return a tuple of the shape of the underlying data.
356 For a Series this is ``(length,)``; for a 1D Index, likewise a
357 single-element tuple. Useful for compatibility with NumPy and
358 other array-like APIs.
360 See Also
361 --------
362 Series.ndim : Number of dimensions of the underlying data.
363 Series.size : Return the number of elements in the underlying data.
364 Series.nbytes : Return the number of bytes in the underlying data.
366 Examples
367 --------
368 >>> s = pd.Series([1, 2, 3])
369 >>> s.shape
370 (3,)
371 """
372 return self._values.shape
374 def __len__(self) -> int:
375 # We need this defined here for mypy
376 raise AbstractMethodError(self)
378 # Temporarily avoid using `-> Literal[1]:` because of an IPython (jedi) bug
379 # https://github.com/ipython/ipython/issues/14412
380 # https://github.com/davidhalter/jedi/issues/1990
381 @property
382 def ndim(self) -> int:
383 """
384 Number of dimensions of the underlying data, by definition 1.
386 Series and Index are one-dimensional; this property always returns 1
387 for compatibility with array-like interfaces.
389 See Also
390 --------
391 Series.size: Return the number of elements in the underlying data.
392 Series.shape: Return a tuple of the shape of the underlying data.
393 Series.dtype: Return the dtype object of the underlying data.
394 Series.values: Return Series as ndarray or ndarray-like depending on the dtype.
396 Examples
397 --------
398 >>> s = pd.Series(["Ant", "Bear", "Cow"])
399 >>> s
400 0 Ant
401 1 Bear
402 2 Cow
403 dtype: str
404 >>> s.ndim
405 1
407 For Index:
409 >>> idx = pd.Index([1, 2, 3])
410 >>> idx
411 Index([1, 2, 3], dtype='int64')
412 >>> idx.ndim
413 1
414 """
415 return 1
417 @final
418 def item(self):
419 """
420 Return the first element of the underlying data as a Python scalar.
422 This method extracts the single element from a length-1 Series or
423 Index and returns it as a native Python scalar type (e.g., ``int``,
424 ``float``, ``str``).
426 Returns
427 -------
428 scalar
429 The first element of Series or Index.
431 Raises
432 ------
433 ValueError
434 If the data is not length = 1.
436 See Also
437 --------
438 Index.values : Returns an array representing the data in the Index.
439 Series.head : Returns the first `n` rows.
441 Examples
442 --------
443 >>> s = pd.Series([1])
444 >>> s.item()
445 1
447 For an index:
449 >>> s = pd.Series([1], index=["a"])
450 >>> s.index.item()
451 'a'
452 """
453 if len(self) == 1:
454 return next(iter(self))
455 raise ValueError("can only convert an array of size 1 to a Python scalar")
457 @property
458 def nbytes(self) -> int:
459 """
460 Return the number of bytes in the underlying data.
462 Includes only the memory used by the array values; overhead such as
463 the index is not included. Useful for estimating memory usage.
465 See Also
466 --------
467 Series.ndim : Number of dimensions of the underlying data.
468 Series.size : Return the number of elements in the underlying data.
470 Examples
471 --------
472 For Series:
474 >>> s = pd.Series(["Ant", "Bear", "Cow"])
475 >>> s
476 0 Ant
477 1 Bear
478 2 Cow
479 dtype: str
480 >>> s.nbytes
481 34
483 For Index:
485 >>> idx = pd.Index([1, 2, 3])
486 >>> idx
487 Index([1, 2, 3], dtype='int64')
488 >>> idx.nbytes
489 24
490 """
491 return self._values.nbytes
493 @property
494 def size(self) -> int:
495 """
496 Return the number of elements in the underlying data.
498 For a Series or Index this is the length (number of rows). Equivalent
499 to ``len(obj)`` and ``np.prod(obj.shape)``.
501 See Also
502 --------
503 Series.ndim: Number of dimensions of the underlying data, by definition 1.
504 Series.shape: Return a tuple of the shape of the underlying data.
505 Series.dtype: Return the dtype object of the underlying data.
506 Series.values: Return Series as ndarray or ndarray-like depending on the dtype.
508 Examples
509 --------
510 For Series:
512 >>> s = pd.Series(["Ant", "Bear", "Cow"])
513 >>> s
514 0 Ant
515 1 Bear
516 2 Cow
517 dtype: str
518 >>> s.size
519 3
521 For Index:
523 >>> idx = pd.Index([1, 2, 3])
524 >>> idx
525 Index([1, 2, 3], dtype='int64')
526 >>> idx.size
527 3
528 """
529 return len(self._values)
531 @property
532 def array(self) -> ExtensionArray:
533 """
534 The ExtensionArray of the data backing this Series or Index.
536 This property provides direct access to the underlying array data of a
537 Series or Index without requiring conversion to a NumPy array. It
538 returns an ExtensionArray, which is the native storage format for
539 pandas extension dtypes.
541 Returns
542 -------
543 ExtensionArray
544 An ExtensionArray of the values stored within. For extension
545 types, this is the actual array. For NumPy native types, this
546 is a thin (no copy) wrapper around :class:`numpy.ndarray`.
548 ``.array`` differs from ``.values``, which may require converting
549 the data to a different form.
551 See Also
552 --------
553 Index.to_numpy : Similar method that always returns a NumPy array.
554 Series.to_numpy : Similar method that always returns a NumPy array.
556 Notes
557 -----
558 This table lays out the different array types for each extension
559 dtype within pandas.
561 ================== =============================
562 dtype array type
563 ================== =============================
564 category Categorical
565 period PeriodArray
566 interval IntervalArray
567 IntegerNA IntegerArray
568 string StringArray
569 boolean BooleanArray
570 datetime64[ns, tz] DatetimeArray
571 ================== =============================
573 For any 3rd-party extension types, the array type will be an
574 ExtensionArray.
576 For all remaining dtypes ``.array`` will be a
577 :class:`arrays.NumpyExtensionArray` wrapping the actual ndarray
578 stored within. If you absolutely need a NumPy array (possibly with
579 copying / coercing data), then use :meth:`Series.to_numpy` instead.
581 Examples
582 --------
583 For regular NumPy types like int, and float, a NumpyExtensionArray
584 is returned.
586 >>> pd.Series([1, 2, 3]).array
587 <NumpyExtensionArray>
588 [1, 2, 3]
589 Length: 3, dtype: int64
591 For extension types, like Categorical, the actual ExtensionArray
592 is returned
594 >>> ser = pd.Series(pd.Categorical(["a", "b", "a"]))
595 >>> ser.array
596 ['a', 'b', 'a']
597 Categories (2, str): ['a', 'b']
598 """
599 raise AbstractMethodError(self)
601 def to_numpy(
602 self,
603 dtype: npt.DTypeLike | None = None,
604 copy: bool = False,
605 na_value: object = lib.no_default,
606 **kwargs,
607 ) -> np.ndarray:
608 """
609 A NumPy ndarray representing the values in this Series or Index.
611 This method converts the underlying data to a NumPy array, optionally
612 specifying the desired dtype and handling of missing values. For
613 extension types, this may require copying data and coercing to a NumPy
614 type.
616 Parameters
617 ----------
618 dtype : str or numpy.dtype, optional
619 The dtype to pass to :meth:`numpy.asarray`.
620 copy : bool, default False
621 Whether to ensure that the returned value is not a view on
622 another array. Note that ``copy=False`` does not *ensure* that
623 ``to_numpy()`` is no-copy. Rather, ``copy=True`` ensure that
624 a copy is made, even if not strictly necessary.
625 na_value : Any, optional
626 The value to use for missing values. The default value depends
627 on `dtype` and the type of the array.
628 **kwargs
629 Additional keywords passed through to the ``to_numpy`` method
630 of the underlying array (for extension arrays).
632 Returns
633 -------
634 numpy.ndarray
635 The NumPy ndarray holding the values from this Series or Index.
636 The dtype of the array may differ. See Notes.
638 See Also
639 --------
640 Series.array : Get the actual data stored within.
641 Index.array : Get the actual data stored within.
642 DataFrame.to_numpy : Similar method for DataFrame.
644 Notes
645 -----
646 The returned array will be the same up to equality (values equal
647 in `self` will be equal in the returned array; likewise for values
648 that are not equal). When `self` contains an ExtensionArray, the
649 dtype may be different. For example, for a category-dtype Series,
650 ``to_numpy()`` will return a NumPy array and the categorical dtype
651 will be lost.
653 For NumPy dtypes, this will be a reference to the actual data stored
654 in this Series or Index (assuming ``copy=False``). Modifying the result
655 in place will modify the data stored in the Series or Index (not that
656 we recommend doing that).
658 For extension types, ``to_numpy()`` *may* require copying data and
659 coercing the result to a NumPy type (possibly object), which may be
660 expensive. When you need a no-copy reference to the underlying data,
661 :attr:`Series.array` should be used instead.
663 This table lays out the different dtypes and default return types of
664 ``to_numpy()`` for various dtypes within pandas.
666 ================== ================================
667 dtype array type
668 ================== ================================
669 category[T] ndarray[T] (same dtype as input)
670 period ndarray[object] (Periods)
671 interval ndarray[object] (Intervals)
672 IntegerNA ndarray[object]
673 datetime64[ns] datetime64[ns]
674 datetime64[ns, tz] ndarray[object] (Timestamps)
675 ================== ================================
677 For timezone-aware datetime data, calling ``to_numpy()`` without
678 specifying ``dtype`` produces an object-dtype array of
679 :class:`Timestamp` objects. This is significantly slower and uses
680 more memory than a native ``datetime64`` array. To avoid this,
681 pass an explicit ``dtype``:
683 - ``dtype="datetime64[ns]"`` converts to UTC and drops the
684 timezone, returning a native ``datetime64[ns]`` array.
685 - ``dtype=object`` explicitly requests Timestamp objects when
686 you need to preserve per-element timezone information.
688 Examples
689 --------
690 >>> ser = pd.Series(pd.Categorical(["a", "b", "a"]))
691 >>> ser.to_numpy()
692 array(['a', 'b', 'a'], dtype=object)
694 Specify the `dtype` to control how datetime-aware data is represented.
695 Use ``dtype=object`` to return an ndarray of pandas :class:`Timestamp`
696 objects, each with the correct ``tz``.
698 >>> ser = pd.Series(pd.date_range("2000", periods=2, tz="CET"))
699 >>> ser.to_numpy(dtype=object)
700 array([Timestamp('2000-01-01 00:00:00+0100', tz='CET'),
701 Timestamp('2000-01-02 00:00:00+0100', tz='CET')],
702 dtype=object)
704 Or ``dtype='datetime64[ns]'`` to return an ndarray of native
705 datetime64 values. The values are converted to UTC and the timezone
706 info is dropped.
708 >>> ser.to_numpy(dtype="datetime64[ns]")
709 ... # doctest: +ELLIPSIS
710 array(['1999-12-31T23:00:00.000000000', '2000-01-01T23:00:00...'],
711 dtype='datetime64[ns]')
712 """
713 if isinstance(self.dtype, ExtensionDtype):
714 return self.array.to_numpy(dtype, copy=copy, na_value=na_value, **kwargs)
715 elif kwargs:
716 bad_keys = next(iter(kwargs.keys()))
717 raise TypeError(
718 f"to_numpy() got an unexpected keyword argument '{bad_keys}'"
719 )
721 fillna = (
722 na_value is not lib.no_default
723 # no need to fillna with np.nan if we already have a float dtype
724 and not (na_value is np.nan and np.issubdtype(self.dtype, np.floating))
725 )
727 values = self._values
728 if fillna and self.hasnans:
729 if not can_hold_element(values, na_value):
730 # if we can't hold the na_value asarray either makes a copy or we
731 # error before modifying values. The asarray later on thus won't make
732 # another copy
733 values = np.asarray(values, dtype=dtype)
734 else:
735 values = values.copy()
737 values[np.asanyarray(isna(self))] = na_value
739 result = np.asarray(values, dtype=dtype)
741 if (copy and not fillna) or not copy:
742 # Check identity first (O(1)) before the more expensive
743 # shares_memory check. Use the already-fetched `values` to
744 # avoid a second _values property access.
745 if result is values or np.shares_memory(values[:2], result[:2]):
746 if not copy:
747 result = result.view()
748 result.flags.writeable = False
749 else:
750 result = result.copy()
752 return result
754 @final
755 @property
756 def empty(self) -> bool:
757 """
758 Indicator whether Index is empty.
760 An Index is considered empty if it has no elements. This property can be
761 useful for quickly checking the state of an Index, especially in data
762 processing and analysis workflows where handling of empty datasets might
763 be required.
765 Returns
766 -------
767 bool
768 If Index is empty, return True, if not return False.
770 See Also
771 --------
772 Index.size : Return the number of elements in the underlying data.
774 Examples
775 --------
776 >>> idx = pd.Index([1, 2, 3])
777 >>> idx
778 Index([1, 2, 3], dtype='int64')
779 >>> idx.empty
780 False
782 >>> idx_empty = pd.Index([])
783 >>> idx_empty
784 Index([], dtype='object')
785 >>> idx_empty.empty
786 True
788 If we only have NaNs in our DataFrame, it is not considered empty!
790 >>> idx = pd.Index([np.nan, np.nan])
791 >>> idx
792 Index([nan, nan], dtype='float64')
793 >>> idx.empty
794 False
795 """
796 return not self.size
798 def argmax(
799 self, axis: AxisInt | None = None, skipna: bool = True, *args, **kwargs
800 ) -> int:
801 """
802 Return int position of the largest value in the Series.
804 If the maximum is achieved in multiple locations,
805 the first row position is returned.
807 Parameters
808 ----------
809 axis : None
810 Unused. Parameter needed for compatibility with DataFrame.
811 skipna : bool, default True
812 Exclude NA/null values. If the entire Series is NA, or if ``skipna=False``
813 and there is an NA value, this method will raise a ``ValueError``.
814 *args, **kwargs
815 Additional arguments and keywords for compatibility with NumPy.
817 Returns
818 -------
819 int
820 Row position of the maximum value.
822 See Also
823 --------
824 Series.argmax : Return position of the maximum value.
825 Series.argmin : Return position of the minimum value.
826 numpy.ndarray.argmax : Equivalent method for numpy arrays.
827 Series.idxmax : Return index label of the maximum values.
828 Series.idxmin : Return index label of the minimum values.
830 Examples
831 --------
832 Consider dataset containing cereal calories
834 >>> s = pd.Series(
835 ... [100.0, 110.0, 120.0, 110.0],
836 ... index=[
837 ... "Corn Flakes",
838 ... "Almond Delight",
839 ... "Cinnamon Toast Crunch",
840 ... "Cocoa Puff",
841 ... ],
842 ... )
843 >>> s
844 Corn Flakes 100.0
845 Almond Delight 110.0
846 Cinnamon Toast Crunch 120.0
847 Cocoa Puff 110.0
848 dtype: float64
850 >>> s.argmax()
851 2
852 >>> s.argmin()
853 0
855 The maximum cereal calories is the third element and
856 the minimum cereal calories is the first element,
857 since series is zero-indexed.
858 """
859 delegate = self._values
860 nv.validate_minmax_axis(axis)
861 skipna = nv.validate_argmax_with_skipna(skipna, args, kwargs)
863 if isinstance(delegate, ExtensionArray):
864 result = delegate.argmax(skipna=skipna)
865 else:
866 # error: Incompatible types in assignment (expression has type
867 # "int | ndarray", variable has type "int")
868 result = nanops.nanargmax( # type: ignore[assignment]
869 delegate, skipna=skipna
870 )
871 return maybe_unbox_numpy_scalar(result)
873 def argmin(
874 self, axis: AxisInt | None = None, skipna: bool = True, *args, **kwargs
875 ) -> int:
876 """
877 Return int position of the smallest value in the Series.
879 If the minimum is achieved in multiple locations,
880 the first row position is returned.
882 Parameters
883 ----------
884 axis : None
885 Unused. Parameter needed for compatibility with DataFrame.
886 skipna : bool, default True
887 Exclude NA/null values. If the entire Series is NA, or if ``skipna=False``
888 and there is an NA value, this method will raise a ``ValueError``.
889 *args, **kwargs
890 Additional arguments and keywords for compatibility with NumPy.
892 Returns
893 -------
894 int
895 Row position of the minimum value.
897 See Also
898 --------
899 Series.argmin : Return position of the minimum value.
900 Series.argmax : Return position of the maximum value.
901 numpy.ndarray.argmin : Equivalent method for numpy arrays.
902 Series.idxmin : Return index label of the minimum values.
903 Series.idxmax : Return index label of the maximum values.
905 Examples
906 --------
907 Consider dataset containing cereal calories
909 >>> s = pd.Series(
910 ... [100.0, 110.0, 120.0, 110.0],
911 ... index=[
912 ... "Corn Flakes",
913 ... "Almond Delight",
914 ... "Cinnamon Toast Crunch",
915 ... "Cocoa Puff",
916 ... ],
917 ... )
918 >>> s
919 Corn Flakes 100.0
920 Almond Delight 110.0
921 Cinnamon Toast Crunch 120.0
922 Cocoa Puff 110.0
923 dtype: float64
925 >>> s.argmax()
926 2
927 >>> s.argmin()
928 0
930 The maximum cereal calories is the third element and
931 the minimum cereal calories is the first element,
932 since series is zero-indexed.
933 """
934 delegate = self._values
935 nv.validate_minmax_axis(axis)
936 skipna = nv.validate_argmax_with_skipna(skipna, args, kwargs)
938 if isinstance(delegate, ExtensionArray):
939 result = delegate.argmin(skipna=skipna)
940 else:
941 # error: Incompatible types in assignment (expression has type
942 # "int | ndarray", variable has type "int")
943 result = nanops.nanargmin( # type: ignore[assignment]
944 delegate, skipna=skipna
945 )
946 return maybe_unbox_numpy_scalar(result)
948 def tolist(self) -> list[Any]:
949 """
950 Return a list of the values.
952 These are each a scalar type, which is a Python scalar
953 (for str, int, float) or a pandas scalar
954 (for Timestamp/Timedelta/Interval/Period)
956 Returns
957 -------
958 list
959 List containing the values as Python or pandas scalers.
961 See Also
962 --------
963 numpy.ndarray.tolist : Return the array as an a.ndim-levels deep
964 nested list of Python scalars.
966 Examples
967 --------
968 For Series
970 >>> s = pd.Series([1, 2, 3])
971 >>> s.to_list()
972 [1, 2, 3]
974 For Index:
976 >>> idx = pd.Index([1, 2, 3])
977 >>> idx
978 Index([1, 2, 3], dtype='int64')
980 >>> idx.to_list()
981 [1, 2, 3]
982 """
983 return self._values.tolist()
985 to_list = tolist
987 def __iter__(self) -> Iterator[Any]:
988 """
989 Return an iterator of the values.
991 These are each a scalar type, which is a Python scalar
992 (for str, int, float) or a pandas scalar
993 (for Timestamp/Timedelta/Interval/Period)
995 Returns
996 -------
997 iterator
998 An iterator yielding scalar values from the Series.
1000 See Also
1001 --------
1002 Series.items : Lazily iterate over (index, value) tuples.
1004 Examples
1005 --------
1006 >>> s = pd.Series([1, 2, 3])
1007 >>> for x in s:
1008 ... print(x)
1009 1
1010 2
1011 3
1012 """
1013 # We are explicitly making element iterators.
1014 if not isinstance(self._values, np.ndarray):
1015 # Check type instead of dtype to catch DTA/TDA
1016 return iter(self._values)
1017 else:
1018 return map(self._values.item, range(self._values.size))
1020 @cache_readonly
1021 def hasnans(self) -> bool:
1022 """
1023 Return True if there are any NaNs.
1025 Enables various performance speedups.
1027 Returns
1028 -------
1029 bool
1031 See Also
1032 --------
1033 Series.isna : Detect missing values.
1034 Series.notna : Detect existing (non-missing) values.
1036 Examples
1037 --------
1038 >>> s = pd.Series([1, 2, 3, None])
1039 >>> s
1040 0 1.0
1041 1 2.0
1042 2 3.0
1043 3 NaN
1044 dtype: float64
1045 >>> s.hasnans
1046 True
1047 """
1048 # error: Item "bool" of "Union[bool, ndarray[Any, dtype[bool_]], NDFrame]"
1049 # has no attribute "any"
1050 return bool(isna(self).any()) # type: ignore[union-attr]
1052 @final
1053 def _map_values(self, mapper, na_action=None):
1054 """
1055 An internal function that maps values using the input
1056 correspondence (which can be a dict, Series, or function).
1058 Parameters
1059 ----------
1060 mapper : function, dict, or Series
1061 The input correspondence object
1062 na_action : {None, 'ignore'}
1063 If 'ignore', propagate NA values, without passing them to the
1064 mapping function
1066 Returns
1067 -------
1068 Union[Index, MultiIndex], inferred
1069 The output of the mapping function applied to the index.
1070 If the function returns a tuple with more than one element
1071 a MultiIndex will be returned.
1072 """
1073 arr = self._values
1075 if isinstance(arr, ExtensionArray):
1076 return arr.map(mapper, na_action=na_action)
1078 return algorithms.map_array(arr, mapper, na_action=na_action)
1080 def value_counts(
1081 self,
1082 normalize: bool = False,
1083 sort: bool = True,
1084 ascending: bool = False,
1085 bins=None,
1086 dropna: bool = True,
1087 ) -> Series:
1088 """
1089 Return a Series containing counts of unique values.
1091 The resulting object will be in descending order so that the
1092 first element is the most frequently-occurring element.
1093 Excludes NA values by default.
1095 Parameters
1096 ----------
1097 normalize : bool, default False
1098 If True then the object returned will contain the relative
1099 frequencies of the unique values.
1100 sort : bool, default True
1101 Stable sort by frequencies when True. Preserve the order of the data
1102 when False.
1104 .. versionchanged:: 3.0.0
1106 Prior to 3.0.0, the sort was unstable.
1107 ascending : bool, default False
1108 Sort in ascending order.
1109 bins : int, optional
1110 Rather than count values, group them into half-open bins,
1111 a convenience for ``pd.cut``, only works with numeric data.
1112 dropna : bool, default True
1113 Don't include counts of NaN.
1115 Returns
1116 -------
1117 Series
1118 Series containing counts of unique values.
1120 See Also
1121 --------
1122 Series.count: Number of non-NA elements in a Series.
1123 DataFrame.count: Number of non-NA elements in a DataFrame.
1124 DataFrame.value_counts: Equivalent method on DataFrames.
1126 Examples
1127 --------
1128 >>> index = pd.Index([3, 1, 2, 3, 4, np.nan])
1129 >>> index.value_counts()
1130 3.0 2
1131 1.0 1
1132 2.0 1
1133 4.0 1
1134 Name: count, dtype: int64
1136 With `normalize` set to `True`, returns the relative frequency by
1137 dividing all values by the sum of values.
1139 >>> s = pd.Series([3, 1, 2, 3, 4, np.nan])
1140 >>> s.value_counts(normalize=True)
1141 3.0 0.4
1142 1.0 0.2
1143 2.0 0.2
1144 4.0 0.2
1145 Name: proportion, dtype: float64
1147 **bins**
1149 Bins can be useful for going from a continuous variable to a
1150 categorical variable; instead of counting unique
1151 apparitions of values, divide the index in the specified
1152 number of half-open bins.
1154 >>> s.value_counts(bins=3)
1155 (0.996, 2.0] 2
1156 (2.0, 3.0] 2
1157 (3.0, 4.0] 1
1158 Name: count, dtype: int64
1160 **dropna**
1162 With `dropna` set to `False` we can also see NaN index values.
1164 >>> s.value_counts(dropna=False)
1165 3.0 2
1166 1.0 1
1167 2.0 1
1168 4.0 1
1169 NaN 1
1170 Name: count, dtype: int64
1172 **Categorical Dtypes**
1174 Rows with categorical type will be counted as one group
1175 if they have same categories and order.
1176 In the example below, even though ``a``, ``c``, and ``d``
1177 all have the same data types of ``category``,
1178 only ``c`` and ``d`` will be counted as one group
1179 since ``a`` doesn't have the same categories.
1181 >>> df = pd.DataFrame({"a": [1], "b": ["2"], "c": [3], "d": [3]})
1182 >>> df = df.astype({"a": "category", "c": "category", "d": "category"})
1183 >>> df
1184 a b c d
1185 0 1 2 3 3
1187 >>> df.dtypes
1188 a category
1189 b str
1190 c category
1191 d category
1192 dtype: object
1194 >>> df.dtypes.value_counts()
1195 category 2
1196 category 1
1197 str 1
1198 Name: count, dtype: int64
1199 """
1200 return algorithms.value_counts_internal(
1201 self,
1202 sort=sort,
1203 ascending=ascending,
1204 normalize=normalize,
1205 bins=bins,
1206 dropna=dropna,
1207 )
1209 def unique(self):
1210 values = self._values
1211 if not isinstance(values, np.ndarray):
1212 # i.e. ExtensionArray
1213 result = values.unique()
1214 else:
1215 result = algorithms.unique1d(values) # type: ignore[assignment]
1216 return result
1218 @final
1219 def nunique(self, dropna: bool = True) -> int:
1220 """
1221 Return number of unique elements in the object.
1223 Excludes NA values by default.
1225 Parameters
1226 ----------
1227 dropna : bool, default True
1228 Don't include NaN in the count.
1230 Returns
1231 -------
1232 int
1233 An integer indicating the number of unique elements in the object.
1235 See Also
1236 --------
1237 DataFrame.nunique: Method nunique for DataFrame.
1238 Series.count: Count non-NA/null observations in the Series.
1240 Examples
1241 --------
1242 >>> s = pd.Series([1, 3, 5, 7, 7])
1243 >>> s
1244 0 1
1245 1 3
1246 2 5
1247 3 7
1248 4 7
1249 dtype: int64
1251 >>> s.nunique()
1252 4
1253 """
1254 uniqs = self.unique()
1255 if dropna:
1256 uniqs = remove_na_arraylike(uniqs)
1257 return len(uniqs)
1259 @property
1260 def is_unique(self) -> bool:
1261 """
1262 Return True if values in the object are unique.
1264 This property checks whether all values in the Series or Index are
1265 distinct, including missing values.
1267 Returns
1268 -------
1269 bool
1271 See Also
1272 --------
1273 Series.unique : Return unique values of Series object.
1274 Series.drop_duplicates : Return Series with duplicate values removed.
1275 Series.duplicated : Indicate duplicate Series values.
1277 Examples
1278 --------
1279 >>> s = pd.Series([1, 2, 3])
1280 >>> s.is_unique
1281 True
1283 >>> s = pd.Series([1, 2, 3, 1])
1284 >>> s.is_unique
1285 False
1286 """
1287 return self.nunique(dropna=False) == len(self)
1289 @property
1290 def is_monotonic_increasing(self) -> bool:
1291 """
1292 Return True if values in the object are monotonically increasing.
1294 This property checks whether each element is greater than or equal to
1295 the previous element. Equal consecutive values are considered
1296 monotonically increasing.
1298 Returns
1299 -------
1300 bool
1302 See Also
1303 --------
1304 Series.is_monotonic_decreasing : Return boolean if values in the object are
1305 monotonically decreasing.
1307 Examples
1308 --------
1309 >>> s = pd.Series([1, 2, 2])
1310 >>> s.is_monotonic_increasing
1311 True
1313 >>> s = pd.Series([3, 2, 1])
1314 >>> s.is_monotonic_increasing
1315 False
1316 """
1317 from pandas import Index
1319 return Index(self).is_monotonic_increasing
1321 @property
1322 def is_monotonic_decreasing(self) -> bool:
1323 """
1324 Return True if values in the object are monotonically decreasing.
1326 This property checks whether each element is less than or equal to
1327 the previous element. Equal consecutive values are considered
1328 monotonically decreasing.
1330 Returns
1331 -------
1332 bool
1334 See Also
1335 --------
1336 Series.is_monotonic_increasing : Return boolean if values in the object are
1337 monotonically increasing.
1339 Examples
1340 --------
1341 >>> s = pd.Series([3, 2, 2, 1])
1342 >>> s.is_monotonic_decreasing
1343 True
1345 >>> s = pd.Series([1, 2, 3])
1346 >>> s.is_monotonic_decreasing
1347 False
1348 """
1349 from pandas import Index
1351 return Index(self).is_monotonic_decreasing
1353 @final
1354 def _memory_usage(self, deep: bool = False) -> int:
1355 """
1356 Memory usage of the values.
1358 Parameters
1359 ----------
1360 deep : bool, default False
1361 Introspect the data deeply, interrogate
1362 `object` dtypes for system-level memory consumption.
1364 Returns
1365 -------
1366 bytes used
1367 Returns memory usage of the values in the Index in bytes.
1369 See Also
1370 --------
1371 numpy.ndarray.nbytes : Total bytes consumed by the elements of the
1372 array.
1374 Notes
1375 -----
1376 Memory usage does not include memory consumed by elements that
1377 are not components of the array if deep=False or if used on PyPy
1379 Examples
1380 --------
1381 >>> idx = pd.Index([1, 2, 3])
1382 >>> idx.memory_usage()
1383 24
1384 """
1385 if hasattr(self.array, "memory_usage"):
1386 return self.array.memory_usage( # pyright: ignore[reportAttributeAccessIssue]
1387 deep=deep,
1388 )
1390 v = self.array.nbytes
1391 if deep and is_object_dtype(self.dtype) and not PYPY:
1392 values = cast("np.ndarray", self._values)
1393 v += lib.memory_usage_of_objects(values)
1394 return v
1396 def factorize(
1397 self,
1398 sort: bool = False,
1399 use_na_sentinel: bool = True,
1400 ) -> tuple[npt.NDArray[np.intp], Index]:
1401 """
1402 Encode the object as an enumerated type or categorical variable.
1404 This method is useful for obtaining a numeric representation of an
1405 array when all that matters is identifying distinct values. `factorize`
1406 is available as both a top-level function :func:`pandas.factorize`,
1407 and as a method :meth:`Series.factorize` and :meth:`Index.factorize`.
1409 Parameters
1410 ----------
1411 sort : bool, default False
1412 Sort `uniques` and shuffle `codes` to maintain the
1413 relationship.
1414 use_na_sentinel : bool, default True
1415 If True, the sentinel -1 will be used for NaN values. If False,
1416 NaN values will be encoded as non-negative integers and will not drop the
1417 NaN from the uniques of the values.
1419 Returns
1420 -------
1421 codes : ndarray
1422 An integer ndarray that's an indexer into `uniques`.
1423 ``uniques.take(codes)`` will have the same values as `values`.
1424 uniques : ndarray, Index, or Categorical
1425 The unique valid values. When `values` is Categorical, `uniques`
1426 is a Categorical. When `values` is some other pandas object, an
1427 `Index` is returned. Otherwise, a 1-D ndarray is returned.
1429 .. note::
1431 Even if there's a missing value in `values`, `uniques` will
1432 *not* contain an entry for it.
1434 See Also
1435 --------
1436 cut : Discretize continuous-valued array.
1437 unique : Find the unique value in an array.
1439 Notes
1440 -----
1441 Reference :ref:`the user guide <reshaping.factorize>` for more examples.
1443 Examples
1444 --------
1445 These examples all show factorize as a top-level method like
1446 ``pd.factorize(values)``. The results are identical for methods like
1447 :meth:`Series.factorize`.
1449 >>> codes, uniques = pd.factorize(
1450 ... np.array(["b", "b", "a", "c", "b"], dtype="O")
1451 ... )
1452 >>> codes
1453 array([0, 0, 1, 2, 0])
1454 >>> uniques
1455 array(['b', 'a', 'c'], dtype=object)
1457 With ``sort=True``, the `uniques` will be sorted, and `codes` will be
1458 shuffled so that the relationship is the maintained.
1460 >>> codes, uniques = pd.factorize(
1461 ... np.array(["b", "b", "a", "c", "b"], dtype="O"), sort=True
1462 ... )
1463 >>> codes
1464 array([1, 1, 0, 2, 1])
1465 >>> uniques
1466 array(['a', 'b', 'c'], dtype=object)
1468 When ``use_na_sentinel=True`` (the default), missing values are indicated in
1469 the `codes` with the sentinel value ``-1`` and missing values are not
1470 included in `uniques`.
1472 >>> codes, uniques = pd.factorize(
1473 ... np.array(["b", None, "a", "c", "b"], dtype="O")
1474 ... )
1475 >>> codes
1476 array([ 0, -1, 1, 2, 0])
1477 >>> uniques
1478 array(['b', 'a', 'c'], dtype=object)
1480 Thus far, we've only factorized lists (which are internally coerced to
1481 NumPy arrays). When factorizing pandas objects, the type of `uniques`
1482 will differ. For Categoricals, a `Categorical` is returned.
1484 >>> cat = pd.Categorical(["a", "a", "c"], categories=["a", "b", "c"])
1485 >>> codes, uniques = pd.factorize(cat)
1486 >>> codes
1487 array([0, 0, 1])
1488 >>> uniques
1489 ['a', 'c']
1490 Categories (3, str): ['a', 'b', 'c']
1492 Notice that ``'b'`` is in ``uniques.categories``, despite not being
1493 present in ``cat.values``.
1495 For all other pandas objects, an Index of the appropriate type is
1496 returned.
1498 >>> cat = pd.Series(["a", "a", "c"])
1499 >>> codes, uniques = pd.factorize(cat)
1500 >>> codes
1501 array([0, 0, 1])
1502 >>> uniques
1503 Index(['a', 'c'], dtype='str')
1505 If NaN is in the values, and we want to include NaN in the uniques of the
1506 values, it can be achieved by setting ``use_na_sentinel=False``.
1508 >>> values = np.array([1, 2, 1, np.nan])
1509 >>> codes, uniques = pd.factorize(values) # default: use_na_sentinel=True
1510 >>> codes
1511 array([ 0, 1, 0, -1])
1512 >>> uniques
1513 array([1., 2.])
1515 >>> codes, uniques = pd.factorize(values, use_na_sentinel=False)
1516 >>> codes
1517 array([0, 1, 0, 2])
1518 >>> uniques
1519 array([ 1., 2., nan])
1520 """
1521 codes, uniques = algorithms.factorize(
1522 self._values, sort=sort, use_na_sentinel=use_na_sentinel
1523 )
1524 if uniques.dtype == np.float16:
1525 uniques = uniques.astype(np.float32)
1527 if isinstance(self, ABCMultiIndex):
1528 # preserve MultiIndex
1529 if len(self) == 0:
1530 # GH#57517
1531 uniques = self[:0]
1532 else:
1533 uniques = self._constructor(uniques)
1534 else:
1535 from pandas import Index
1537 try:
1538 uniques = Index(uniques, dtype=self.dtype, copy=False)
1539 except NotImplementedError:
1540 # not all dtypes are supported in Index that are allowed for Series
1541 # e.g. float16 or bytes
1542 uniques = Index(uniques, copy=False)
1543 return codes, uniques
1545 # This overload is needed so that the call to searchsorted in
1546 # pandas.core.resample.TimeGrouper._get_period_bins picks the correct result
1548 # error: Overloaded function signatures 1 and 2 overlap with incompatible
1549 # return types
1550 @overload
1551 def searchsorted( # type: ignore[overload-overlap]
1552 self,
1553 value: ScalarLike_co,
1554 side: Literal["left", "right"] = ...,
1555 sorter: NumpySorter = ...,
1556 ) -> np.intp: ...
1558 @overload
1559 def searchsorted(
1560 self,
1561 value: npt.ArrayLike | ExtensionArray,
1562 side: Literal["left", "right"] = ...,
1563 sorter: NumpySorter = ...,
1564 ) -> npt.NDArray[np.intp]: ...
1566 def searchsorted(
1567 self,
1568 value: NumpyValueArrayLike | ExtensionArray,
1569 side: Literal["left", "right"] = "left",
1570 sorter: NumpySorter | None = None,
1571 ) -> npt.NDArray[np.intp] | np.intp:
1572 """
1573 Find indices where elements should be inserted to maintain order.
1575 Find the indices into a sorted Index `self` such that, if the
1576 corresponding elements in `value` were inserted before the indices,
1577 the order of `self` would be preserved.
1579 .. note::
1581 The Index *must* be monotonically sorted, otherwise
1582 wrong locations will likely be returned. Pandas does *not*
1583 check this for you.
1585 Parameters
1586 ----------
1587 value : array-like or scalar
1588 Values to insert into `self`.
1589 side : {'left', 'right'}, optional
1590 If 'left', the index of the first suitable location found is given.
1591 If 'right', return the last such index. If there is no suitable
1592 index, return either 0 or N (where N is the length of `self`).
1593 sorter : 1-D array-like, optional
1594 Optional array of integer indices that sort `self` into ascending
1595 order. They are typically the result of ``np.argsort``.
1597 Returns
1598 -------
1599 int or array of int
1600 A scalar or array of insertion points with the
1601 same shape as `value`.
1603 See Also
1604 --------
1605 sort_values : Sort by the values along either axis.
1606 numpy.searchsorted : Similar method from NumPy.
1608 Notes
1609 -----
1610 Binary search is used to find the required insertion points.
1612 Examples
1613 --------
1614 >>> ser = pd.Series([1, 2, 3])
1615 >>> ser
1616 0 1
1617 1 2
1618 2 3
1619 dtype: int64
1621 >>> ser.searchsorted(4)
1622 3
1624 >>> ser.searchsorted([0, 4])
1625 array([0, 3])
1627 >>> ser.searchsorted([1, 3], side="left")
1628 array([0, 2])
1630 >>> ser.searchsorted([1, 3], side="right")
1631 array([1, 3])
1633 >>> ser = pd.Series(pd.to_datetime(["3/11/2000", "3/12/2000", "3/13/2000"]))
1634 >>> ser
1635 0 2000-03-11
1636 1 2000-03-12
1637 2 2000-03-13
1638 dtype: datetime64[us]
1640 >>> ser.searchsorted("3/14/2000")
1641 3
1643 >>> ser = pd.Categorical(
1644 ... ["apple", "bread", "bread", "cheese", "milk"], ordered=True
1645 ... )
1646 >>> ser
1647 ['apple', 'bread', 'bread', 'cheese', 'milk']
1648 Categories (4, str): ['apple' < 'bread' < 'cheese' < 'milk']
1650 >>> ser.searchsorted("bread")
1651 np.int64(1)
1653 >>> ser.searchsorted(["bread"], side="right")
1654 array([3])
1656 If the values are not monotonically sorted, wrong locations
1657 may be returned:
1659 >>> ser = pd.Series([2, 1, 3])
1660 >>> ser
1661 0 2
1662 1 1
1663 2 3
1664 dtype: int64
1666 >>> ser.searchsorted(1) # doctest: +SKIP
1667 0 # wrong result, correct would be 1
1668 """
1669 if isinstance(value, ABCDataFrame):
1670 msg = (
1671 "Value must be 1-D array-like or scalar, "
1672 f"{type(value).__name__} is not supported"
1673 )
1674 raise ValueError(msg)
1676 values = self._values
1677 if not isinstance(values, np.ndarray):
1678 # Going through EA.searchsorted directly improves performance GH#38083
1679 result = values.searchsorted(value, side=side, sorter=sorter)
1680 else:
1681 result = algorithms.searchsorted(
1682 values,
1683 value,
1684 side=side,
1685 sorter=sorter,
1686 )
1687 return maybe_unbox_numpy_scalar(result)
1689 def drop_duplicates(self, *, keep: DropKeep = "first") -> Self:
1690 duplicated = self._duplicated(keep=keep)
1691 # error: Value of type "IndexOpsMixin" is not indexable
1692 return self[~duplicated] # type: ignore[index]
1694 @final
1695 def _duplicated(self, keep: DropKeep = "first") -> npt.NDArray[np.bool_]:
1696 arr = self._values
1697 if isinstance(arr, ExtensionArray):
1698 return arr.duplicated(keep=keep)
1699 return algorithms.duplicated(arr, keep=keep)
1701 def _arith_method(self, other, op):
1702 res_name = ops.get_op_result_name(self, other)
1704 lvalues = self._values
1705 if not isinstance(lvalues, ExtensionArray) or isinstance(other, range):
1706 # For EA-backed values the warning is emitted by the EA's own
1707 # _arith_method; the exception is ``range``, which is converted to
1708 # an ndarray below before it reaches the EA (GH#62423).
1709 ops.maybe_warn_listlike(other)
1710 rvalues = extract_array(other, extract_numpy=True, extract_range=True)
1711 rvalues = ops.maybe_prepare_scalar_for_op(rvalues, lvalues.shape)
1712 rvalues = ensure_wrapped_if_datetimelike(rvalues)
1713 if isinstance(rvalues, range):
1714 rvalues = np.arange(rvalues.start, rvalues.stop, rvalues.step)
1716 with np.errstate(all="ignore"):
1717 result = ops.arithmetic_op(lvalues, rvalues, op)
1719 return self._construct_result(result, name=res_name, other=other)
1721 def _construct_result(self, result, name, other):
1722 """
1723 Construct an appropriately-wrapped result from the ArrayLike result
1724 of an arithmetic-like operation.
1725 """
1726 raise AbstractMethodError(self)