17

I have the below series:

my_series = pd.Series([np.nan, np.nan, ['A', 'B']])

I have to loop through my_series and evaluate whether the value is NaN or not and then do something (actions defined as 'do A' and 'do B' for the sake of simplicity).

1st try:

for element in my_series:
    if element.isna():
        print('do A')
    else:
        print('do B')

When running it, I've got the error: "'float' object has no attribute 'isna'"

2nd try from the question: Error: float object has no attribute notnull

for element in my_series:
    np.where(element.isnull(), 'do A', 'do B')

When running it, I've got the error: "AttributeError: 'float' object has no attribute 'isnull'"

I haven't found any other similar question here at StackOverflow, I don't know what else to try.

asa
  • 675
  • 2
  • 7
  • 17
  • Try using `np.isnan()` in the second loop: `for element in my_series: np.where(np.isnan(element), 'do A', 'do B')` – Peter Leimbigler Nov 30 '19 at 16:25
  • Tried and got the following error: " ufunc 'isnan' not supported for the input types, and the inputs could not be safely coerced to any supported types according to the casting rule ''safe'' " – asa Nov 30 '19 at 16:29
  • 1
    Oops, then try `pd.isna()`: `for element in my_series: np.where(pd.isna(element), 'do A', 'do B')` – Peter Leimbigler Nov 30 '19 at 16:31

2 Answers2

18

Change your code to:

for element in my_series:
    if type(element) == float and pd.isna(element):
        print('do A')
    else:
        print('do B')

Edit following the comment by Peter

I on purpose didn't change the original concept of processing the source Series in a loop. It looks like both print instructions are rather "placeholders", to be replaced with one piece of code for NaN values and another for other values.

Valdi_Bo
  • 30,023
  • 4
  • 23
  • 41
  • 1
    `pd.isna()` accepts any scalar or array-like object, not just floats. There is no need to check for `if type(element) == float`. Also, explicit for-looping over series values is slow. – Peter Leimbigler Nov 30 '19 at 16:43
  • Initially I tried as you suggested. But if the current element is a **list** (as in the case of the last element), I got: *ValueError: The truth value of an array with more than one element is ambiguous. Use a.any() or a.all()*. This is why I added checking for *float* type. – Valdi_Bo Nov 30 '19 at 16:47
6

No need for explicit for loops. Based on your second attempt:

# Setup
my_series = pd.Series([np.nan, np.nan, ['A', 'B']])

# Solution
np.where(my_series.isnull(), 'do A', 'do B')                                              

# Output
array(['do A', 'do A', 'do B'], dtype='<U4')
Peter Leimbigler
  • 10,775
  • 1
  • 23
  • 37