1515import warnings
1616
1717from pandas .util ._decorators import (
18- doc ,
1918 set_module ,
2019)
2120from pandas .util ._exceptions import find_stack_level
@@ -236,12 +235,11 @@ def __get__(self, obj, cls):
236235CachedAccessor = Accessor
237236
238237
239- @doc (klass = "" , examples = "" , others = "" )
240238def _register_accessor (
241239 name : str , cls : type [NDFrame | Index ]
242240) -> Callable [[TypeT ], TypeT ]:
243241 """
244- Register a custom accessor on {klass} objects.
242+ Register a custom accessor on objects.
245243
246244 Parameters
247245 ----------
@@ -262,14 +260,15 @@ def _register_accessor(
262260
263261 Notes
264262 -----
265- This function allows you to register a custom-defined accessor class for {klass}.
263+ This function allows you to register a custom-defined accessor class
264+ for pandas objects (DataFrame, Series, or Index).
266265 The requirements for the accessor class are as follows:
267266
268267 * Must contain an init method that:
269268
270- * accepts a single {klass} object
269+ * accepts a single object
271270
272- * raises an AttributeError if the {klass} object does not have correctly
271+ * raises an AttributeError if the object does not have correctly
273272 matching inputs for the accessor
274273
275274 * Must contain a method for each access pattern.
@@ -279,9 +278,6 @@ def _register_accessor(
279278 * Accessible using the @property decorator if no additional arguments are
280279 needed.
281280
282- Examples
283- --------
284- {examples}
285281 """
286282
287283 def decorator (accessor : TypeT ) -> TypeT :
@@ -327,8 +323,73 @@ def decorator(accessor: TypeT) -> TypeT:
327323
328324
329325@set_module ("pandas.api.extensions" )
330- @doc (_register_accessor , klass = "DataFrame" , examples = _register_df_examples )
331326def register_dataframe_accessor (name : str ) -> Callable [[TypeT ], TypeT ]:
327+ """
328+ Register a custom accessor on DataFrame objects.
329+
330+ Parameters
331+ ----------
332+ name : str
333+ Name under which the accessor should be registered. A warning is issued
334+ if this name conflicts with a preexisting attribute.
335+
336+ Returns
337+ -------
338+ callable
339+ A class decorator.
340+
341+ See Also
342+ --------
343+ register_dataframe_accessor : Register a custom accessor on DataFrame objects.
344+ register_series_accessor : Register a custom accessor on Series objects.
345+ register_index_accessor : Register a custom accessor on Index objects.
346+
347+ Notes
348+ -----
349+ This function allows you to register a custom-defined accessor class for DataFrame.
350+ The requirements for the accessor class are as follows:
351+
352+ * Must contain an init method that:
353+
354+ * accepts a single DataFrame object
355+
356+ * raises an AttributeError if the DataFrame object does not have correctly
357+ matching inputs for the accessor
358+
359+ * Must contain a method for each access pattern.
360+
361+ * The methods should be able to take any argument signature.
362+
363+ * Accessible using the @property decorator if no additional arguments are
364+ needed.
365+
366+ Examples
367+ --------
368+ An accessor that only accepts integers could
369+ have a class defined like this:
370+
371+ >>> @pd.api.extensions.register_dataframe_accessor("int_accessor")
372+ ... class IntAccessor:
373+ ... def __init__(self, pandas_obj):
374+ ... if not all(
375+ ... pandas_obj[col].dtype == "int64" for col in pandas_obj.columns
376+ ... ):
377+ ... raise AttributeError("All columns must contain integer values only")
378+ ... self._obj = pandas_obj
379+ ...
380+ ... def sum(self):
381+ ... return self._obj.sum()
382+ >>> df = pd.DataFrame([[1, 2], ["x", "y"]])
383+ >>> df.int_accessor
384+ Traceback (most recent call last):
385+ ...
386+ AttributeError: All columns must contain integer values only.
387+ >>> df = pd.DataFrame([[1, 2], [3, 4]])
388+ >>> df.int_accessor.sum()
389+ 0 4
390+ 1 6
391+ dtype: int64
392+ """
332393 from pandas import DataFrame
333394
334395 return _register_accessor (name , DataFrame )
@@ -359,8 +420,69 @@ def register_dataframe_accessor(name: str) -> Callable[[TypeT], TypeT]:
359420
360421
361422@set_module ("pandas.api.extensions" )
362- @doc (_register_accessor , klass = "Series" , examples = _register_series_examples )
363423def register_series_accessor (name : str ) -> Callable [[TypeT ], TypeT ]:
424+ """
425+ Register a custom accessor on Series objects.
426+
427+ Parameters
428+ ----------
429+ name : str
430+ Name under which the accessor should be registered. A warning is issued
431+ if this name conflicts with a preexisting attribute.
432+
433+ Returns
434+ -------
435+ callable
436+ A class decorator.
437+
438+ See Also
439+ --------
440+ register_dataframe_accessor : Register a custom accessor on DataFrame objects.
441+ register_series_accessor : Register a custom accessor on Series objects.
442+ register_index_accessor : Register a custom accessor on Index objects.
443+
444+ Notes
445+ -----
446+ This function allows you to register a custom-defined accessor class for Series.
447+ The requirements for the accessor class are as follows:
448+
449+ * Must contain an init method that:
450+
451+ * accepts a single Series object
452+
453+ * raises an AttributeError if the Series object does not have correctly
454+ matching inputs for the accessor
455+
456+ * Must contain a method for each access pattern.
457+
458+ * The methods should be able to take any argument signature.
459+
460+ * Accessible using the @property decorator if no additional arguments are
461+ needed.
462+
463+ Examples
464+ --------
465+ An accessor that only accepts integers could
466+ have a class defined like this:
467+
468+ >>> @pd.api.extensions.register_series_accessor("int_accessor")
469+ ... class IntAccessor:
470+ ... def __init__(self, pandas_obj):
471+ ... if not pandas_obj.dtype == "int64":
472+ ... raise AttributeError("The series must contain integer data only")
473+ ... self._obj = pandas_obj
474+ ...
475+ ... def sum(self):
476+ ... return self._obj.sum()
477+ >>> df = pd.Series([1, 2, "x"])
478+ >>> df.int_accessor
479+ Traceback (most recent call last):
480+ ...
481+ AttributeError: The series must contain integer data only.
482+ >>> df = pd.Series([1, 2, 3])
483+ >>> df.int_accessor.sum()
484+ np.int64(6)
485+ """
364486 from pandas import Series
365487
366488 return _register_accessor (name , Series )
@@ -394,8 +516,73 @@ def register_series_accessor(name: str) -> Callable[[TypeT], TypeT]:
394516
395517
396518@set_module ("pandas.api.extensions" )
397- @doc (_register_accessor , klass = "Index" , examples = _register_index_examples )
398519def register_index_accessor (name : str ) -> Callable [[TypeT ], TypeT ]:
520+ """
521+ Register a custom accessor on Index objects.
522+
523+ Parameters
524+ ----------
525+ name : str
526+ Name under which the accessor should be registered. A warning is issued
527+ if this name conflicts with a preexisting attribute.
528+
529+ Returns
530+ -------
531+ callable
532+ A class decorator.
533+
534+ See Also
535+ --------
536+ register_dataframe_accessor : Register a custom accessor on DataFrame objects.
537+ register_series_accessor : Register a custom accessor on Series objects.
538+ register_index_accessor : Register a custom accessor on Index objects.
539+
540+ Notes
541+ -----
542+ This function allows you to register a custom-defined accessor class for Index.
543+ The requirements for the accessor class are as follows:
544+
545+ * Must contain an init method that:
546+
547+ * accepts a single Index object
548+
549+ * raises an AttributeError if the Index object does not have correctly
550+ matching inputs for the accessor
551+
552+ * Must contain a method for each access pattern.
553+
554+ * The methods should be able to take any argument signature.
555+
556+ * Accessible using the @property decorator if no additional arguments are
557+ needed.
558+
559+ Examples
560+ --------
561+ An accessor that only accepts integers could
562+ have a class defined like this:
563+
564+ >>> @pd.api.extensions.register_index_accessor("int_accessor")
565+ ... class IntAccessor:
566+ ... def __init__(self, pandas_obj):
567+ ... if not all(isinstance(x, int) for x in pandas_obj):
568+ ... raise AttributeError("The index must only be an integer value")
569+ ... self._obj = pandas_obj
570+ ...
571+ ... def even(self):
572+ ... return [x for x in self._obj if x % 2 == 0]
573+ >>> df = pd.DataFrame.from_dict(
574+ ... {"row1": {"1": 1, "2": "a"}, "row2": {"1": 2, "2": "b"}}, orient="index"
575+ ... )
576+ >>> df.index.int_accessor
577+ Traceback (most recent call last):
578+ ...
579+ AttributeError: The index must only be an integer value.
580+ >>> df = pd.DataFrame(
581+ ... {"col1": [1, 2, 3, 4], "col2": ["a", "b", "c", "d"]}, index=[1, 2, 5, 8]
582+ ... )
583+ >>> df.index.int_accessor.even()
584+ [2, 8]
585+ """
399586 from pandas import Index
400587
401588 return _register_accessor (name , Index )
0 commit comments