pandas.DataFrame.round() not accepting pd.NA or pd.NAN

Viewed 1879

pandas version: 1.2

I have a dataframe that columns as 'float64' with null values represented as pd.NAN. Is there way to round without converting to string then decimal:

df = pd.DataFrame([(.21, .3212), (.01, .61237), (.66123, .03), (.21, .18),(pd.NA, .18)],
                  columns=['dogs', 'cats'])
df
      dogs     cats
0     0.21  0.32120
1     0.01  0.61237
2  0.66123  0.03000
3     0.21  0.18000
4     <NA>  0.18000

Here is what I wanted to do, but it is erroring:

df['dogs'] = df['dogs'].round(2)

TypeError: float() argument must be a string or a number, not 'NAType'

Here is another way I tried but this silently fails and no conversion occurs:

tn.round({'dogs': 1})

      dogs     cats
0     0.21  0.32120
1     0.01  0.61237
2  0.66123  0.03000
3     0.21  0.18000
4     <NA>  0.18000
3 Answers

While annoying, the pandas.NA is still relatively new and doesn't support ALL numpy ufuncs. Oddly I'm also encountering errors trying to change the "dogs" column's dtype from object -> float which seems like a bug to me. There's a couple of alternatives that you can achieve your desired result though:

  • mask the NA away and round the rest of the column
na_mask = df["dogs"].notnull()
df.loc[na_mask, "dogs"] = df.loc[na_mask, "dogs"].astype(float).round(1)

print(df)
   dogs     cats
0   0.2  0.32120
1     0  0.61237
2   0.7  0.03000
3   0.2  0.18000
4  <NA>  0.18000
  • Replace the pd.NA with np.nan and then round
df = df.replace(pd.NA, np.nan).round({"dogs": 1})

print(df)
   dogs     cats
0   0.2  0.32120
1   0.0  0.61237
2   0.7  0.03000
3   0.2  0.18000
4   NaN  0.18000
df['dogs'] = df['dogs'].apply(lambda x: round(x,2) if str(x) != '<NA>' else x)

Does the following code work?

import pandas as pd
import numpy as np

df = pd.DataFrame([(.21, .3212), (.01, .61237), (.66123, .03), (.21, .18), (np.nan, .18)],
                  columns=['dogs', 'cats'])

df['dogs'] = df['dogs'].round(2)
print(df)
Related