I have used the Ivan Mishalkins handy solution in our in-house python library extensively. At some point I thought, it would be better to use his solution in form of a decorator. The only restriction is that the first argument of decorated function must be a DataFrame:
from copy import deepcopy
from functools import wraps
import pandas as pd
from pandas.core.base import PandasObject
def as_method(func):
"""
This decrator makes a function also available as a method.
The first passed argument must be a DataFrame.
"""
@wraps(func)
def wrapper(*args, **kwargs):
return func(*deepcopy(args), **deepcopy(kwargs))
setattr(PandasObject, wrapper.__name__, wrapper)
return wrapper
@as_method
def augment_x(DF, x):
"""We will be able to see this docstring if we run ??augment_x"""
DF[f"column_{x}"] = x
return DF
Example:
df = pd.DataFrame({"A": [1, 2]})
df
A
0 1
1 2
df.augment_x(10)
A column_10
0 1 10
1 2 10
As you can see, the original DataFrame is not changed. As if there is a inplace = False
df
A
0 1
1 2
You can still use the augment_x
as a simple function:
augment_x(df, 2)
A column_2
0 1 2
1 2 2
apply
. For exampledf.apply(myfunc)
I realize this doesn't create a new method, but perhaps it gets you what you need, at the very least you can do method chaining this way `df.apply(myfunc).apply(myotherfunc)
...apply
method? How complex is your method?pandas.api.extensions.register_dataframe_accessor()
. There is a long list of extensions in the pandas ecosystem page.