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,14 @@ 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 for .
266264 The requirements for the accessor class are as follows:
267265
268266 * Must contain an init method that:
269267
270- * accepts a single {klass} object
268+ * accepts a single object
271269
272- * raises an AttributeError if the {klass} object does not have correctly
270+ * raises an AttributeError if the object does not have correctly
273271 matching inputs for the accessor
274272
275273 * Must contain a method for each access pattern.
@@ -281,7 +279,7 @@ def _register_accessor(
281279
282280 Examples
283281 --------
284- {examples}
282+
285283 """
286284
287285 def decorator (accessor : TypeT ) -> TypeT :
@@ -327,8 +325,73 @@ def decorator(accessor: TypeT) -> TypeT:
327325
328326
329327@set_module ("pandas.api.extensions" )
330- @doc (_register_accessor , klass = "DataFrame" , examples = _register_df_examples )
331328def register_dataframe_accessor (name : str ) -> Callable [[TypeT ], TypeT ]:
329+ """
330+ Register a custom accessor on DataFrame objects.
331+
332+ Parameters
333+ ----------
334+ name : str
335+ Name under which the accessor should be registered. A warning is issued
336+ if this name conflicts with a preexisting attribute.
337+
338+ Returns
339+ -------
340+ callable
341+ A class decorator.
342+
343+ See Also
344+ --------
345+ register_dataframe_accessor : Register a custom accessor on DataFrame objects.
346+ register_series_accessor : Register a custom accessor on Series objects.
347+ register_index_accessor : Register a custom accessor on Index objects.
348+
349+ Notes
350+ -----
351+ This function allows you to register a custom-defined accessor class for DataFrame.
352+ The requirements for the accessor class are as follows:
353+
354+ * Must contain an init method that:
355+
356+ * accepts a single DataFrame object
357+
358+ * raises an AttributeError if the DataFrame object does not have correctly
359+ matching inputs for the accessor
360+
361+ * Must contain a method for each access pattern.
362+
363+ * The methods should be able to take any argument signature.
364+
365+ * Accessible using the @property decorator if no additional arguments are
366+ needed.
367+
368+ Examples
369+ --------
370+ An accessor that only accepts integers could
371+ have a class defined like this:
372+
373+ >>> @pd.api.extensions.register_dataframe_accessor("int_accessor")
374+ ... class IntAccessor:
375+ ... def __init__(self, pandas_obj):
376+ ... if not all(
377+ ... pandas_obj[col].dtype == "int64" for col in pandas_obj.columns
378+ ... ):
379+ ... raise AttributeError("All columns must contain integer values only")
380+ ... self._obj = pandas_obj
381+ ...
382+ ... def sum(self):
383+ ... return self._obj.sum()
384+ >>> df = pd.DataFrame([[1, 2], ["x", "y"]])
385+ >>> df.int_accessor
386+ Traceback (most recent call last):
387+ ...
388+ AttributeError: All columns must contain integer values only.
389+ >>> df = pd.DataFrame([[1, 2], [3, 4]])
390+ >>> df.int_accessor.sum()
391+ 0 4
392+ 1 6
393+ dtype: int64
394+ """
332395 from pandas import DataFrame
333396
334397 return _register_accessor (name , DataFrame )
@@ -359,8 +422,69 @@ def register_dataframe_accessor(name: str) -> Callable[[TypeT], TypeT]:
359422
360423
361424@set_module ("pandas.api.extensions" )
362- @doc (_register_accessor , klass = "Series" , examples = _register_series_examples )
363425def register_series_accessor (name : str ) -> Callable [[TypeT ], TypeT ]:
426+ """
427+ Register a custom accessor on Series objects.
428+
429+ Parameters
430+ ----------
431+ name : str
432+ Name under which the accessor should be registered. A warning is issued
433+ if this name conflicts with a preexisting attribute.
434+
435+ Returns
436+ -------
437+ callable
438+ A class decorator.
439+
440+ See Also
441+ --------
442+ register_dataframe_accessor : Register a custom accessor on DataFrame objects.
443+ register_series_accessor : Register a custom accessor on Series objects.
444+ register_index_accessor : Register a custom accessor on Index objects.
445+
446+ Notes
447+ -----
448+ This function allows you to register a custom-defined accessor class for Series.
449+ The requirements for the accessor class are as follows:
450+
451+ * Must contain an init method that:
452+
453+ * accepts a single Series object
454+
455+ * raises an AttributeError if the Series object does not have correctly
456+ matching inputs for the accessor
457+
458+ * Must contain a method for each access pattern.
459+
460+ * The methods should be able to take any argument signature.
461+
462+ * Accessible using the @property decorator if no additional arguments are
463+ needed.
464+
465+ Examples
466+ --------
467+ An accessor that only accepts integers could
468+ have a class defined like this:
469+
470+ >>> @pd.api.extensions.register_series_accessor("int_accessor")
471+ ... class IntAccessor:
472+ ... def __init__(self, pandas_obj):
473+ ... if not pandas_obj.dtype == "int64":
474+ ... raise AttributeError("The series must contain integer data only")
475+ ... self._obj = pandas_obj
476+ ...
477+ ... def sum(self):
478+ ... return self._obj.sum()
479+ >>> df = pd.Series([1, 2, "x"])
480+ >>> df.int_accessor
481+ Traceback (most recent call last):
482+ ...
483+ AttributeError: The series must contain integer data only.
484+ >>> df = pd.Series([1, 2, 3])
485+ >>> df.int_accessor.sum()
486+ np.int64(6)
487+ """
364488 from pandas import Series
365489
366490 return _register_accessor (name , Series )
@@ -394,8 +518,73 @@ def register_series_accessor(name: str) -> Callable[[TypeT], TypeT]:
394518
395519
396520@set_module ("pandas.api.extensions" )
397- @doc (_register_accessor , klass = "Index" , examples = _register_index_examples )
398521def register_index_accessor (name : str ) -> Callable [[TypeT ], TypeT ]:
522+ """
523+ Register a custom accessor on Index objects.
524+
525+ Parameters
526+ ----------
527+ name : str
528+ Name under which the accessor should be registered. A warning is issued
529+ if this name conflicts with a preexisting attribute.
530+
531+ Returns
532+ -------
533+ callable
534+ A class decorator.
535+
536+ See Also
537+ --------
538+ register_dataframe_accessor : Register a custom accessor on DataFrame objects.
539+ register_series_accessor : Register a custom accessor on Series objects.
540+ register_index_accessor : Register a custom accessor on Index objects.
541+
542+ Notes
543+ -----
544+ This function allows you to register a custom-defined accessor class for Index.
545+ The requirements for the accessor class are as follows:
546+
547+ * Must contain an init method that:
548+
549+ * accepts a single Index object
550+
551+ * raises an AttributeError if the Index object does not have correctly
552+ matching inputs for the accessor
553+
554+ * Must contain a method for each access pattern.
555+
556+ * The methods should be able to take any argument signature.
557+
558+ * Accessible using the @property decorator if no additional arguments are
559+ needed.
560+
561+ Examples
562+ --------
563+ An accessor that only accepts integers could
564+ have a class defined like this:
565+
566+ >>> @pd.api.extensions.register_index_accessor("int_accessor")
567+ ... class IntAccessor:
568+ ... def __init__(self, pandas_obj):
569+ ... if not all(isinstance(x, int) for x in pandas_obj):
570+ ... raise AttributeError("The index must only be an integer value")
571+ ... self._obj = pandas_obj
572+ ...
573+ ... def even(self):
574+ ... return [x for x in self._obj if x % 2 == 0]
575+ >>> df = pd.DataFrame.from_dict(
576+ ... {"row1": {"1": 1, "2": "a"}, "row2": {"1": 2, "2": "b"}}, orient="index"
577+ ... )
578+ >>> df.index.int_accessor
579+ Traceback (most recent call last):
580+ ...
581+ AttributeError: The index must only be an integer value.
582+ >>> df = pd.DataFrame(
583+ ... {"col1": [1, 2, 3, 4], "col2": ["a", "b", "c", "d"]}, index=[1, 2, 5, 8]
584+ ... )
585+ >>> df.index.int_accessor.even()
586+ [2, 8]
587+ """
399588 from pandas import Index
400589
401590 return _register_accessor (name , Index )
0 commit comments