Pandas apply function - args how is it passed

Viewed 236
df = pd.read_csv('https://raw.githubusercontent.com/selva86/datasets/master/Cars93_miss.csv')
d = {'Min.Price': np.nanmean, 'Max.Price': np.nanmedian}
df[['Min.Price', 'Max.Price']] = df[['Min.Price', 'Max.Price']].apply(lambda x, d: x.fillna(d[x.name](x)), args=(d, ))

apply(lambda x, d: x.fillna(d[x.name](x)), args=(d, )) - Am not understanding this part. I know how apply and fillna works but with this args it's confusing.

  1. why does args have comma at the end
  2. what does the d actually pass -
2 Answers

To more directly answer your question:

  1. args is a tuple, and a single element tuple requires a trailing comma in order to properly be identified as a tuple and not just a parameterized object.
  2. d is your dictionary, and when it's being passed at the end I believe it is your current list after having the lambda function applied to each element in the dictionary saying that if the element is NaN or N/A (ie Null/missing) then it will fill them with the given value specified. pandas.DataFrame.fillna Hopefully that helps.

As you know, df.apply function applies a function to the DataFrame's elements. Now this function normally takes only one argument. When you need to use a multi argument function with df.apply, you can specify the other arguments with the args parameter

From the docstring (print(pd.DataFrame.apply.__doc__))

args : tuple
    Positional arguments to pass to `func` in addition to the
    array/series.

Here you are using two argument function with lambda x, d: therefore you need to specify the 2nd argument with args=. Here it is expecting a tuple with the arguments

To put a single element into a tuple, you need to put it into brackets with a trailing comma.

print(1)                                                                              
>>>1
print((1,))                                                                           
>>>(1,)

To put the variable d into a tuple, you need to do (d,)

The dictionary contains two separate functions for the two columns with column names as its keys. So x being the column passed into the lambda function, x.name gives you the column name and d[x.name] gives you the function intended for that column name. Then that function is applied to the column.

For the 'Min.Price' column the function is np.nanmean. So d[x.name](x) is evaluated to np.nanmean(x) which gives you the column mean excluding nans. Now you're using the mean value to fill the nans in the original column by doing x.fillna(d[x.name](x))

Related