Python Pandas: применить функцию, используя имена столбцов в качестве именованных аргументов - PullRequest
2 голосов
/ 18 октября 2019

Есть ли в пандах способ применить функцию к кадру данных, используя имена столбцов в качестве имен аргументов? Например, у меня есть функция и датафрейм.

df = pd.DataFrame({'A':[1,2,3],
               'B':[1,2,3],
               'C':[1,2,3],
               'D':[1,2,3]})    
def f(A,B,C):
   #Pretend code is more complicated
   return A + B + C

Есть ли способ, которым я могу сделать что-то вроде

df.apply(f)

и заставить панд сопоставлять столбцы с именованными аргументами?

Я знаю, что могу переписать функциювзять строку вместо именованных аргументов, но имейте в виду, что f - просто игрушечный пример, и моя реальная функция более сложна

РЕДАКТИРОВАТЬ:

Понял это на основе ответа @ juanpa.arrivillaga:

df[list(f.__code__.co_varnames)].apply((lambda row: f(**row)), axis=1)

Ответы [ 4 ]

1 голос
/ 18 октября 2019

Применяемая функция f должна принимать либо строки / столбцы, в зависимости от axis=0,1, либо df в качестве аргумента, но не имя столбца. Вы можете написать обертку для этой цели.

def wrapper(x, A, B, C):
    return f(x[A], x[B], x[C])

df.apply(wrapper, axis=1, args=('A','B','C'))

Вывод:

0    3
1    6
2    9
dtype: int64
1 голос
/ 18 октября 2019

Хорошего пути нет в общем . Однако, если имена ваших столбцов горят точно , вы можете обернуть функцию в другую функцию, которая разбивает аргумент строки в вашей функции, потому что Series объекты являются отображениями!

Так дано:

>>> import pandas as pd
>>> df = pd.DataFrame({'A':[1,2,3],
...                'B':[1,2,3],
...                'C':[1,2,3],
...                'D':[1,2,3]})
>>> df
   A  B  C  D
0  1  1  1  1
1  2  2  2  2
2  3  3  3  3
>>> def f(A, B, C): return A + B + C
...

Мы могли бы почти сделать:

>>> df.apply(lambda row: f(**row), axis=1)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/Users/juan/anaconda3/envs/ecqm-catalog/lib/python3.7/site-packages/pandas/core/frame.py", line 6014, in apply
    return op.get_result()
  File "/Users/juan/anaconda3/envs/ecqm-catalog/lib/python3.7/site-packages/pandas/core/apply.py", line 142, in get_result
    return self.apply_standard()
  File "/Users/juan/anaconda3/envs/ecqm-catalog/lib/python3.7/site-packages/pandas/core/apply.py", line 248, in apply_standard
    self.apply_series_generator()
  File "/Users/juan/anaconda3/envs/ecqm-catalog/lib/python3.7/site-packages/pandas/core/apply.py", line 277, in apply_series_generator
    results[i] = self.f(v)
  File "<stdin>", line 1, in <lambda>
TypeError: ("f() got an unexpected keyword argument 'D'", 'occurred at index 0')

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

>>> df.drop('D',axis=1).apply(lambda row: f(**row), axis=1)
0    3
1    6
2    9
1 голос
/ 18 октября 2019

, если вас интересует функция «применить», вот случай

df = pd.DataFrame({'A':[1,2,3],
                  'B':[1,2,3],
                  'C':[1,2,3],
                  'D':[1,2,3]})     


def func(row):
    row['result'] = row['A'] + row['B'] + row['C']
    return row

df.apply(func, axis = 1)


    Out[67]: 
       A  B  C  D  result
    0  1  1  1  1       3
    1  2  2  2  2       6
    2  3  3  3  3       9

UPD

Если вы должны использовать функцию «f» и не хотите ее менять, может быть это:

df['res'] = f(df['A'], df['B'], df['C'])
df

    Out[70]: 
       A  B  C  D  res
    0  1  1  1  1    3
    1  2  2  2  2    6
    2  3  3  3  3    9
0 голосов
/ 18 октября 2019

Понял, строю из ответа @ juanpa.arrivillaga.

df[list(f.__code__.co_varnames)].apply((lambda row: f(**row)), axis=1)

...