Reputation:
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
Reputation: 1923
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.
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
.
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 tuple
s.
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 :
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
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