I have a sample dataframe and function below. I created a function that will get the coordinates of a 'cell' and put that in a tuple, along with the reason why it was put there. I want this function to also change the value of a certain column.
import pandas as pd
import numpy as np
df1 = pd.DataFrame({'A' : [np.NaN,np.NaN,3,4,5,5,3,1,5,np.NaN],
'B' : [1,0,3,5,0,0,np.NaN,9,0,0],
'C' : [10,0,30,50,0,0,4,10,1,0],
'D' : [1,0,3,4,0,0,7,8,0,1],
'E' : [np.nan,'Unassign','Assign','Ugly','Appreciate',
'Undo','Assign','Unicycle','Assign','Unicorn',]})
print(df1)
highlights = []
def find_nan(list_col):
for c in list_col:
# if column is one of the dataframe's columns, go
if c in df1.columns:
# for each index x where column c of the dataframe is null, go
for x in df1.loc[df1[c].isnull()].index: #appends to the list of tuples
highlights.append(
tuple([x + 2, df1.columns.get_loc(c) + 1, f'{c} is Null in row {x + 2}']))
df1.iloc[x, df1.columns.get_loc('E')] = f'{c} is blank in row {x + 2}'
find_nan(['A','B'])
# using the function above, checks for all nulls in A and B
# Also places the coordinates and reason in a tuple and changes values of column 'E'
#output:
A B C D E
0 NaN 1.0 10 1 A is blank in row 2
1 NaN 0.0 0 0 A is blank in row 3
2 3.0 3.0 30 3 Assign
3 4.0 5.0 50 4 Ugly
4 5.0 0.0 0 0 Appreciate
5 5.0 0.0 0 0 Undo
6 3.0 NaN 4 7 Assign
7 1.0 9.0 10 8 Unicycle
8 5.0 0.0 1 0 Assign
9 NaN 0.0 0 1 A is blank in row 11
What I want to do is add logic that will add the reasons together if E is already populated, or simply change the value of E if null. Here is my issue: using df1.iloc I cannot seem to check for nulls.
df1.iloc[0]['E'].isnull() returns AttributeError: 'float' object has no attribute 'isnull' (obviously)
to get around that: I can use if np.isnan(df1.iloc[0]['E']) which evaluates to True, but if there is a value already in E I will get a TypeError.
Essentially what I want is this sort of logic within my function:
if df1.iloc[x]['E'] is null:
df1.iloc[x, df1.columns.get_loc('E')] = 'PREVIOUS_VALUE' + f'{c} is blank in row {x + 2}'
else:
df1.iloc[x, df1.columns.get_loc('E')] = f'{c} is blank in row {x + 2}
Expected output from my function on the original dataframe:
find_nan(['A','B'])
A B C D E
0 NaN 1.0 10 1 A is blank in row 2
1 NaN 0.0 0 0 Unassign and A is blank in row 3
2 3.0 3.0 30 3 Assign
3 4.0 5.0 50 4 Ugly
4 5.0 0.0 0 0 Appreciate
5 5.0 0.0 0 0 Undo
6 3.0 NaN 4 7 Assign and B is blank in row 8
7 1.0 9.0 10 8 Unicycle
8 5.0 0.0 1 0 Assign
9 NaN 0.0 0 1 Unicorn and A is blank in row 11
Using Python 3.6. this is part of a bigger project with more functions, hence the 'adding of reasons' and the adding of 2 to the index 'for no apparent reason'