39

I have been struggling with this question for a long while, and I tried different methods.

I have a simple DataFrame as shown,

enter image description here

I can use code to replace NaN with None (Not String "None"),

[![dfTest2 = dfTest.where(pd.notnull(dfTest), None)][2]][2]

enter image description here

I support that NaT is also classified as 'Null' because the following, enter image description here

However, NaT is not replaced with None.

I have been searching for answers but got no luck. Anyone could Help?

Thank you in advance.

Haipeng Su
  • 2,021
  • 2
  • 13
  • 30

5 Answers5

43

Make the dtype object

dfTest2 = pd.DataFrame(dict(InvoiceDate=pd.to_datetime(['2017-06-01', pd.NaT])))

dfTest2.InvoiceDate.astype(object).where(dfTest2.InvoiceDate.notnull(), None)

0    2017-06-01 00:00:00
1                   None
Name: InvoiceDate, dtype: object
piRSquared
  • 265,629
  • 48
  • 427
  • 571
  • 1
    Amazing!!! Thank you so so much. Totally make sense, the Timestamp type gives default NaT for Null. Thx again. – Haipeng Su Mar 15 '17 at 21:12
  • 4
    I don't wanna change the type of object and want it only in datetime format so this solution isn't working for me. – renny May 06 '19 at 06:16
  • Your code gives me only the column affected as a result. But I want this to happen in in the DF itself and the original column replaced by this new one with None's. How to do that? – Aakash Basu Apr 30 '20 at 07:09
  • Assign the result back to the dataframe – piRSquared Apr 30 '20 at 07:31
25

The simplest solution I found that worked for me is...

Input:

import pandas as pd
import numpy as np
dfTest = pd.DataFrame(dict(InvoiceDate=pd.to_datetime(['2017-06-01', pd.NaT]), CorpId=[2997373, np.nan], TestName=[1,1]))
dfTest.replace({np.nan: None}, inplace = True)

Output of dfTest:

enter image description here

LucyDrops
  • 389
  • 3
  • 11
dshefman
  • 777
  • 8
  • 17
4

Make the column type as str first

 dfTest2.InvoiceDate =  dfTest2.InvoiceDate.astype(str)

then compare it directly with "NaT" and replace with None

dfTest2.InvoiceDate = dfTest2.InvoiceDate.apply(lambda x : None if x=="NaT" else x)
Rahul Agarwal
  • 3,940
  • 7
  • 26
  • 47
2

Similar approach as suggested by @neerajYadav but without the apply:

dfTest2['InvoiceDate'] = (dfTest2['InvoiceDate']
                          .astype(str) # <- cast to string to simplify
                                       #    .replace() in newer versions
                          .replace({'NaT': None} # <- replace with None
                         )
Snake Verde
  • 545
  • 2
  • 10
  • This will change the column type to str, which in some cases we don't want that to happen – knl Apr 18 '22 at 07:10
0

If you don't want to change the type of the column, then another alternative is to to replace all missing values (pd.NaT) first with np.nan and then replace the latter with None:

import numpy as np

df = df.fillna(np.nan).replace([np.nan], [None])
Giorgos Myrianthous
  • 30,279
  • 17
  • 114
  • 133