I am developing an API in django-rest-framework where depending on your input parameters you get different responses. The API is calculating indicators that will return to the user against a database.
I wrote a function to handle NaN values like so:
def nan_to_none(value):
if not isinstance(value, str) and value is not None and np.isnan(value):
return None
return value
This is the element of the response where the error pops:
"prog": nan_to_none(row["average_items_prog"])
This is the line of SQL that is raising the issue:
((((coalesce(qte_art, 0) / nullif(nb_client, 0)) - (coalesce(qte_art_n1, 0) / nullif(nb_client_n1, 0))) / (coalesce(qte_art_n1, 0) / nullif(nb_client_n1, 0))) * 100) as average_items_prog,
And this is the error message:
File "C:\Users\wdc\views.py", line 464, in get
"prog": nan_to_none(row["average_items_prog"])},
File "C:\Users\wdc\views.py", line 28, in nan_to_none
if not isinstance(value, str) and value is not None and np.isnan(value):
File "C:\ProgramData\Anaconda3\lib\site-packages\pandas\core\generic.py", line 1478, in __nonzero__
.format(self.__class__.__name__))
ValueError: The truth value of a Series is ambiguous. Use a.empty, a.bool(), a.item(), a.any() or a.all().
I have no clue how to fix this !
Try change:
"prog": nan_to_none(row["average_items_prog"])
with Series.apply
:
"prog": row["average_items_prog"].apply(nan_to_none)
Test:
s = pd.Series(['a', 0, 0, 1, None, np.nan])
print (s)
0 a
1 0
2 0
3 1
4 None
5 NaN
dtype: object
def nan_to_none(value):
if not isinstance(value, str) and value is not None and np.isnan(value):
return None
return value
print (s.apply(nan_to_none))
#in your solution
#"prog": row["average_items_prog"].apply(nan_to_none)
0 a
1 0
2 0
3 1
4 None
5 None
dtype: object
Also seems solution should be simplify with testing np.nan != np.nan
:
def nan_to_none(value):
if value != value:
return None
return value
print (s.apply(nan_to_none))
#in your solution
#"prog": row["average_items_prog"].apply(nan_to_none)
0 a
1 0
2 0
3 1
4 None
5 None
dtype: object
Or set None
with Series.mask
:
print (s.mask(s.isna(), None))
#in your solution
#"prog": row["average_items_prog"].mask(s.isna(), None)
0 a
1 0
2 0
3 1
4 None
5 None
dtype: object