如何将 pandas 方法作为参数传递?

Sar*_*ahD 2 python parameter-passing pandas

我有一个计算 pandas 数据框的列模式的函数:

def my_func(df):
    for col in df.columns:
        stat = df[col].mode()
        print(stat)
Run Code Online (Sandbox Code Playgroud)

但我想让它更通用,以便我可以更改我计算的统计数据,例如平均值,最大值,...我尝试将方法 mode() 作为参数传递给我的函数:

def my_func(df, pandas_stat):
    for col in df.columns:
        stat = df[col].pandas_stat()
        print(stat)
Run Code Online (Sandbox Code Playgroud)

参考:如何在 Python 中将方法作为参数传递

然而这似乎对我不起作用。使用一个简单的例子:

> A
     a    b
0  1.0  2.0
1  2.0  4.0
2  2.0  6.0
3  3.0  NaN
4  NaN  4.0
5  3.0  NaN
6  2.0  6.0
7  4.0  6.0
Run Code Online (Sandbox Code Playgroud)

它无法识别命令模式:

> my_func(A, mode)
Traceback (most recent call last):

  File "<ipython-input-332-c137de83a530>", line 1, in <module>
    my_func(A, mode)

NameError: name 'mode' is not defined
Run Code Online (Sandbox Code Playgroud)

所以我尝试了 pd.DataFrame.mode:

> my_func(A, pd.DataFrame.mode)
Traceback (most recent call last):

  File "<ipython-input-334-dd913410abd0>", line 1, in <module>
    my_func(A, pd.DataFrame.mode)

  File "<ipython-input-329-8acf337bce92>", line 3, in my_func
    stat = df[col].pandas_stat()

  File "/anaconda3/envs/py36/lib/python3.6/site-packages/pandas/core/generic.py", line 4376, in __getattr__
    return object.__getattribute__(self, name)

AttributeError: 'Series' object has no attribute 'pandas_stat'
Run Code Online (Sandbox Code Playgroud)

有没有办法传递模式函数?

Mik*_*nov 6

您可以使用[getattr][1]内置和__name__属性来执行此操作,但我想这会使您的代码有些不清楚。可能存在更好的方法。

df = pd.DataFrame({'col1': list(range(5)), 'col2': list(range(5, 0, -1))})
df
Out:
   col1  col2
0     0     5
1     1     4
2     2     3
3     3     2
4     4     1
Run Code Online (Sandbox Code Playgroud)

定义my_func这种方式并将其应用于df

def my_func(df, pandas_stat):
    for col in df.columns:
        stat = getattr(df[col], pandas_stat.__name__)()
        print(stat)

my_func(df, pd.DataFrame.mean)
Out
2.0
3.0
Run Code Online (Sandbox Code Playgroud)

说明:pd.DataFrame.mean具有__name__值为 的属性'mean'。Getattr 可以从pd.DataFrame对象中获取该属性,然后调用它。

如果需要,您甚至可以传递参数:

def my_func(df, pandas_stat, *args, **kwargs):
    for col in df.columns:
        stat = getattr(df[col], pandas_stat.__name__)(*args, **kwargs)
        print(stat)

my_func(df, pd.DataFrame.apply, lambda x: x ** 2)
Out: 
0     0
1     1
2     4
3     9
4    16
Name: col1, dtype: int64
0    25
1    16
2     9
3     4
4     1
Name: col2, dtype: int64
Run Code Online (Sandbox Code Playgroud)

但我再说一遍,我想这种方法有点令人困惑。

编辑
关于错误:

> my_func(A, pd.DataFrame.mode)
Traceback (most recent call last):

  File "<ipython-input-334-dd913410abd0>", line 1, in <module>
    my_func(A, pd.DataFrame.mode)

  File "<ipython-input-329-8acf337bce92>", line 3, in my_func
    stat = df[col].pandas_stat()

  File "/anaconda3/envs/py36/lib/python3.6/site-packages/pandas/core/generic.py", line 4376, in __getattr__
    return object.__getattribute__(self, name)

AttributeError: 'Series' object has no attribute 'pandas_stat'
Run Code Online (Sandbox Code Playgroud)

df[col].pandas_stat()执行时,点.运算符调用__getattribute__数据帧对象的方法。它类似于 a getattr,但它self自动作为第一个参数。
因此,第二个是方法的“名称”,它位于'pandas_stat'您的代码中。它破坏了执行,因为 pandas dataframe 没有具有此类名称的属性。

如果您向 提供了实际方法的正确名称(“mean”、“apply”等)getattr,则此函数会在pd.DataFrame.__dict__列出所有方法的位置找到该方法,并将其返回。所以你可以通过语法来调用它(*args, **kwargs)