Return the last not null, nan, and non empty value from a python list
Question:
How can I return the last not null, not empty, and not nan from a list?
if not exists, then return "null" or a customized message!
I have tried these pieces of codes and none of them is bullet proof:
import numpy as np
listF=[0.0,np. NaN,2,0,0.0,""]
print([j for j in listF if j][-1])#returns 2 while should retrun 0
listF=[0.0,np. NaN,np. NaN,0,0.0,np. NaN]
print([j for j in listF if j][-1])#returns nan while should return 0
listF=[]
print([j for j in listF if j][-1])#returns Index out of range
listF=[1,np. NaN,np. NaN,0,0.0,np. NaN]
print([j for j in listF if j][-1])#returns nan while should return 0
listF=[np. NaN,np. NaN,np. NaN]
print([j for j in listF if j][-1])#returns nan while should return "null"
Answers:
You can use math.isnan
(or numpy.isnan
) to check the NA status. Combine it with a generator and next
with a default value to handle cases without valid value:
from math import isnan
def last_valid(lst):
return next((x for x in reversed(lst) if x and not isnan(x)), None) # or 'null'
last_valid([])
# None
last_valid([0.0,np. NaN,2,0,0.0,""])
# 2
last_valid([1,np. NaN,np. NaN,0,0.0,np. NaN])
# 1
last_valid([0.0,np. NaN,np. NaN,0,0.0,np. NaN])
# None
accepting 0
as valid:
Given your update of the rule (0 was initially described as non-valid), you can convert to string in the first test to consider 0
valid:
from math import isnan
def last_valid(lst):
return next((x for x in reversed(lst) if str(x) and not isnan(x)), '"null"')
last_valid([]))
# '"null"'
last_valid([0.0,np. NaN,2,0,0.0,""])
# 0.0
last_valid([1,np. NaN,np. NaN,0,0.0,np. NaN])
# 0.0
last_valid([0.0,np. NaN,np. NaN,0,0.0,np. NaN])
# 0.0
last_valid([np. NaN,np. NaN,np. NaN])
# '"null"'
import numpy as np
import pandas as pd
listF=[0.0,np. NaN,2,0,0.0,""]
output = 'empty list'
for tmp in listF[::-1]:
if not tmp or pd.isna(tmp):
continue
else:
output = tmp
break
output
>>> bool(np.nan)
True
>>> bool('')
False
>>> bool(0.0)
False
A more general method is to create a forbiden set and use it to filter the original list.
fset = set(['', np.nan, None])
valid_list = [j for j in listF if j not in fset]
To get the last one,
last = valid_list[-1] if valid_list else "null"
This is the oneliner you almost got.
You have to keep in mind that nan is not false when in a bolean expression!
But always returns false if compared to itself 🙂
print([i for i in list if i and not i!=i][-1])
How can I return the last not null, not empty, and not nan from a list?
if not exists, then return "null" or a customized message!
I have tried these pieces of codes and none of them is bullet proof:
import numpy as np
listF=[0.0,np. NaN,2,0,0.0,""]
print([j for j in listF if j][-1])#returns 2 while should retrun 0
listF=[0.0,np. NaN,np. NaN,0,0.0,np. NaN]
print([j for j in listF if j][-1])#returns nan while should return 0
listF=[]
print([j for j in listF if j][-1])#returns Index out of range
listF=[1,np. NaN,np. NaN,0,0.0,np. NaN]
print([j for j in listF if j][-1])#returns nan while should return 0
listF=[np. NaN,np. NaN,np. NaN]
print([j for j in listF if j][-1])#returns nan while should return "null"
You can use math.isnan
(or numpy.isnan
) to check the NA status. Combine it with a generator and next
with a default value to handle cases without valid value:
from math import isnan
def last_valid(lst):
return next((x for x in reversed(lst) if x and not isnan(x)), None) # or 'null'
last_valid([])
# None
last_valid([0.0,np. NaN,2,0,0.0,""])
# 2
last_valid([1,np. NaN,np. NaN,0,0.0,np. NaN])
# 1
last_valid([0.0,np. NaN,np. NaN,0,0.0,np. NaN])
# None
accepting 0
as valid:
Given your update of the rule (0 was initially described as non-valid), you can convert to string in the first test to consider 0
valid:
from math import isnan
def last_valid(lst):
return next((x for x in reversed(lst) if str(x) and not isnan(x)), '"null"')
last_valid([]))
# '"null"'
last_valid([0.0,np. NaN,2,0,0.0,""])
# 0.0
last_valid([1,np. NaN,np. NaN,0,0.0,np. NaN])
# 0.0
last_valid([0.0,np. NaN,np. NaN,0,0.0,np. NaN])
# 0.0
last_valid([np. NaN,np. NaN,np. NaN])
# '"null"'
import numpy as np
import pandas as pd
listF=[0.0,np. NaN,2,0,0.0,""]
output = 'empty list'
for tmp in listF[::-1]:
if not tmp or pd.isna(tmp):
continue
else:
output = tmp
break
output
>>> bool(np.nan)
True
>>> bool('')
False
>>> bool(0.0)
False
A more general method is to create a forbiden set and use it to filter the original list.
fset = set(['', np.nan, None])
valid_list = [j for j in listF if j not in fset]
To get the last one,
last = valid_list[-1] if valid_list else "null"
This is the oneliner you almost got.
You have to keep in mind that nan is not false when in a bolean expression!
But always returns false if compared to itself 🙂
print([i for i in list if i and not i!=i][-1])