user14571893
user14571893

Reputation:

'numpy.int64' has no len()

Error:

TypeError: object of type 'numpy.int64' has no len()

Code:

import numpy as np

def apk(actual, predicted, k=10):

    if len(predicted)>k: # here is the error
        predicted = predicted[:k]

    score = 0.0
    num_hits = 0.0

    for i,p in enumerate(predicted):
        if p in actual and p not in predicted[:i]:
            num_hits += 1.0
            score += num_hits / (i+1.0)

    if not actual:
        return 1.0

    return score / min(len(actual), k)

def mapk(actual, predicted, k=10):
    print(type(predicted))
    >>> <class 'list'> # here is predicted also from the value list
    return np.mean([apk(a,p,k) for a,p in zip(actual, predicted)])




x = list(df_new['id'].to_numpy())
y = list(re['id'].to_numpy())

print(type(y))
>>> <class 'list'>
# So y is a list and not like later 'numpy.int64'
mapk(x,y)

When I start the following call I get the following error, how do I resolve it?
When I do the following, I get the length len(y) How do I solve this error? I am very much looking forward to answers.

Upvotes: 0

Views: 4362

Answers (2)

Rivers
Rivers

Reputation: 1923

How to debug your code:

With the informations you provide, the problem is that the type of predicted is numpy.int64. And an int has, indeed, no len. I suppose that predicted should be a list ?

Try to print the type of predicted before the line where you get the error:

def apk(actual, predicted, k=10):
    print(type(predicted)) # Add this code
    if len(predicted)>k: # here is the error

The error appears in the apk function.

The line causing the error:

And @Daniel F explains in his answer why predicted is not of type list:

Because what you pass as an argument as the parameter named predicted to the apk function is NOT the variable predicted you have in the mapk function. In fact, you pass the variable p to apk, which is not the list named predicted. And, from the error message, we deduce that p is of type numpy.64.

This is the line where you pass p as an argument for the parameter named predicted, to your function apk: [apk(a,p,k) for a,p in zip(actual, predicted)]

If you change this code to this (I'm not saying you should do this, because from what you provide we can't do more than making assumptions):

[apk(a,predicted,k) for a,p in zip(actual, predicted)]

Then, you will not pass p, but you will pass predicted as an argument for the parameter named predicted, to your function apk.

Detail explanation on what is going on :

I'll go in depth, my excuses if it seems too exagerated.

I'll will explain here the line [apk(a,predicted,k) for a,p in zip(actual, predicted)]:

Here is a simple example of how zip works:

a = [1,2,3]
b = [4,5,6]
c = list(zip(a,b))

c will be a list of tuples.

Each tuple will contains two variables of type int. Values of c : [(1, 4), (2, 5), (3, 6)]

So when you'll iterate through c you will get :

  • (1, 4) at the first iteration
  • (2, 5) at the second iteration
  • and (3, 6) at the third iteration.

Example code:

for a_tuple in c:
    a,p = a_tuple
    print(a) # 1 at 1st iter, 2 at 2nd,and 3 at 3rd
    print(p) # 4 at 1st iter, 5 at 2nd,and 6 at 3rd

When we write:

a,p = (1,2)

we will assigne the first element of the tuple to a and the second to p. So a == 1 and p == 2.

If we write a,b,c = (1,2,3): a == 1, b == 2, and c == 3.

Now, we will decompose your list comprehension as a for loop:

If you set actual = [1,2,3] and predicted = [4,5,6], then, writing:

[apk(a,p,k) for a,p in zip(actual, predicted)]

is the same as writing:

k = 2
zipped = zip(actual, predicted)
# list(zipped) == [(1, 4), (2, 5), (3, 6)]

for a,p in zipped:
    apk(a,p,k) # p == 4 at 1st iter, 5 at 2nd,and 6 at 3rd. p is an element of a tuple of the zipped list

To conclude: you have to determine what sould be the types of actual and predited, inside (in its scope) the function named apk.

Upvotes: 0

Daniel F
Daniel F

Reputation: 14399

You're iterating through predicted in this line:

return np.mean([apk(a,p,k) for a,p in zip(actual, predicted)])

predicted is a list, but p is just an element of that list.

In the scope of apk, predicted is p (not the predicted from mapk) - and thus, apparently, int64.

Upvotes: 1

Related Questions