28

Suppose I have a dataframe like this:

df = pd.DataFrame([['foo', 'x'], ['bar', 'y']], columns=['A', 'B'])


       A    B
0    foo    x
1    bar    y

I know how to use a single argument function with Apply when it comes to dataframes, like this:

def some_func(row):
    return '{0}-{1}'.format(row['A'], row['B'])

df['C'] = df.apply(some_func, axis=1)

df


       A    B        C
0    foo    x    foo-x
1    bar    y    bar-y

How can I use apply on dataframes when they involve multiple input arguments? Here's an example of what I want:

def some_func(row, var1):
    return '{0}-{1}-{2}'.format(row['A'], row['B'], var1)

df['C'] = df.apply(some_func(row, var1='DOG'), axis=1)

df


       A    B            C
0    foo    x    foo-x-DOG
1    bar    y    bar-y-DOG

I'm not looking for work-arounds to solve this one particular example, just how to do something like this in general. Any advice would be well appreciated, thanks.

cs95
  • 379,657
  • 97
  • 704
  • 746
Michael Henry
  • 345
  • 1
  • 3
  • 5

3 Answers3

42

It's just the way you think it would be, apply accepts args and kwargs and passes them directly to some_func.

df.apply(some_func, var1='DOG', axis=1)

Or,

df.apply(some_func, args=('DOG', ), axis=1)

<!- ->

0    foo-x-DOG
1    bar-y-DOG
dtype: object

If for any reason that won't work for your use case, then you can always fallback to using a lambda:

df.apply(lambda row: some_func(row, 'DOG'), axis=1)

0    foo-x-DOG
1    bar-y-DOG
dtype: object
cs95
  • 379,657
  • 97
  • 704
  • 746
6

You should use vectorized logic:

df['C'] = df['A'] + '-' + df['B'] + '-DOG'

If you really want to use df.apply, which is just a thinly veiled loop, you can simply feed your arguments as additional parameters:

def some_func(row, var1):
    return '{0}-{1}-{2}'.format(row['A'], row['B'], var1)

df['C'] = df.apply(some_func, var1='DOG', axis=1)

As per the docs, df.apply accepts both positional and keyword arguments.

Chidi
  • 901
  • 11
  • 15
jpp
  • 159,742
  • 34
  • 281
  • 339
  • 1
    You are correct in your suggestion for vectorized logic for this particular example. But thank you for answering the exact question anyway :). – XiB Oct 15 '21 at 09:30
2

I think it can be

df.apply('-'.join,1)+'-DOG'
Out[157]: 
0    foo-x-DOG
1    bar-y-DOG
dtype: object
BENY
  • 317,841
  • 20
  • 164
  • 234