Как передать метод панды в качестве параметра? - PullRequest
0 голосов
/ 18 января 2019

У меня есть функция, которая рассчитывает режим столбцов пандасфрейма данных:

def my_func(df):
    for col in df.columns:
        stat = df[col].mode()
        print(stat)

Но я бы хотел сделать его более общим, чтобы я мог изменить статистику, которую я вычисляю, например. значит, макс ... Я пытался передать метод mode () в качестве аргумента моей функции:

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

ссылаясь на: Как передать метод в качестве параметра в 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

Не распознает командный режим:

> 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

поэтому я попытался 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'

Есть ли способ передать функцию mode?

Ответы [ 2 ]

0 голосов
/ 18 января 2019

Вы можете сделать это с помощью getattr:

def my_func(df, pandas_stat):
    for col in df.columns:
        print(getattr(df[col], pandas_stat)())  # the empty parenthesis
                                                       # are required to call
                                                       # the method

df_max = my_func(df, "max")
0 голосов
/ 18 января 2019

Вы можете использовать встроенные атрибуты [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

Определите 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

Объяснение: 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

Но я повторяю, я думаю, этот подход немного сбивает с толку.

Редактировать
Об ошибке:

> 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'

Когда выполняется df[col].pandas_stat(), оператор точки . вызывает метод __getattribute__ объекта dataframe. Это аналог getattr, но он автоматически получает self в качестве первого аргумента.
Итак, второе - это имя метода, которое 'pandas_stat' в вашем коде. Это нарушает выполнение, потому что у информационного кадра pandas нет атрибута с таким именем.

Если вы предоставите правильное имя фактического метода («среднее», «применить» или около того) для getattr, эта функция найдет этот метод в pd.DataFrame.__dict__, где перечислены все методы, и вернет его. Так что вы можете вызвать его с помощью синтаксиса (*args, **kwargs).

...