12

I have a method called counting that takes 2 arguments. I need to call this method using the apply() method. However when I am passing the two parameters to the apply method it is giving the following error:

TypeError: counting() takes exactly 2 arguments (1 given)

I have seen the following thread python pandas: apply a function with arguments to a series. Update and I do not want to use functool.partial as I do not want to import additional classes to be able to pass parameters.

def counting(dic, strWord):
    if strWord in dic:
        return dic[strWord]
    else:
        return 0

DF['new_column'] = DF['dic_column'].apply(counting, 'word')

If I give a single parameter, it works:

def awesome_count(dic):
    if strWord in dic:
       return dic[strWord]
    else:
       return 0

DF['new_column'] = DF['dic_column'].apply(counting)
3
  • What is dic and where do you expect it to come from? Also, what's your problem with partial? It's part of the standard library ... Commented Oct 19, 2015 at 0:18
  • Where did you want the second argument to come from? Commented Oct 19, 2015 at 0:20
  • Modified the question for more clarity. dic is the column value that would come by default via the apply function. The second argument is a new argument that is being passed using logic. Commented Oct 19, 2015 at 0:24

2 Answers 2

21

You could just use a lambda:

DF['new_column'] = DF['dic_column'].apply(lambda dic: counting(dic, 'word'))

On the other hand, there's absolutely nothing wrong with using partial here:

from functools import partial
count_word = partial(counting, strWord='word')
DF['new_column'] = DF['dic_column'].apply(count_word)

As @EdChum mentions, if your counting method is actually just looking up a word or defaulting it to zero, you can just use the handy dict.get method instead of writing one yourself:

DF['new_column'] = DF['dic_column'].apply(lambda dic: dic.get('word', 0))

And a non-lambda way to do the above, via the operator module:

from operator import methodcaller
count_word = methodcaller(get, 'word', 0)
DF['new_column'] = DF['dic_column'].apply(count_word)
Sign up to request clarification or add additional context in comments.

4 Comments

This gives me the required solution. Thank you. To your earlier question, I had assumed that this method would be better than using partial. Is it correct? Also, if possible, kindly confirm my understanding of this solution that here the value of the column is passed to the variable dic that is then passed to the method counting along with another variable value.
partial is equivalent here, lambda isn't 'better' in any way: e.g. countWord = partial(counting, strWord='word') and then apply(countWord). And yes, your understanding is correct.
I think in this case you can just do DF['new_column'] = DF['dic_column'].apply(lambda x: dic.get(x,0))
@EdChum not quite, the since the dictionary is the parameter to the lambda, not the word being looked up. But yeah, if counting is actually that simple, it can just be lambda dic: dic.get('word', 0).
3

The accepted answer is totally perfect. Taught me some interesting things about Python. But just for fun, here's more precisely what we're looking for:

selected_words =  ['awesome', 'great', 'fantastic', 'amazing', 'love', 'horrible', 'bad', 'terrible', 'awful', 'wow', 'hate']
for this_word in selected_words:
    products[this_word] = products['word_count'].apply(lambda dic: dic.get(this_word, 0))

Thanks for posting the question!

1 Comment

I'd like to know why this works ¿is just a matter of scoping?

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.