python原生的None和pandas, numpy中的numpy.NaN尽管在功能上都是用来标示空缺数据。但它们的行为在很多场景下确有一些相当大的差异。由于不熟悉这些差异,曾经给我的工作带来过不少麻烦。 特此整理了一份详细的实验,比较None和NaN在不同场景下的差异。
实验的结果有些在意料之内,有些则让我大跌眼镜。希望读者看过此文后会None和NaN这对“小妖精”有更深的理解。
为了理解本文的内容,希望本文的读者需要对pandas的Series使用有一定的经验。
首先,导入所需的库
In[2]:
Python
1
2
3fromnumpyimportNaN
frompandasimportSeries,DataFrame
importnumpyasnp
数据类型?
None是一个python特殊的数据类型, 但是NaN却是用一个特殊的float
In[3]:
Python
1
type(None)
Out[3]:
Python
1NoneType
In[4]:
Python
1
type(NaN)
Out[4]:
Python
1float
能作为dict的key?
In[5]:
Python
1
{None:1}
Out[5]:
Python
1{None:1}
In[6]:
Python
1
{NaN:1}
Out[6]:
Python
1{nan:1}
In[7]:
Python
1
{None:1,NaN:2}
Out[7]:
Python
1{nan:2,None:1}
都可以,而且会被认为是不同的key
Series函数中的表现
Series.map
In[8]:
Python
1
2
s=Series([None,NaN,'a'])
s
Out[8]:
Python
1
2
3
40None
1NaN
2a
dtype:object
In[9]:
Python
1
s.map({None:1,'a':'a'})
Out[9]:
Python
1
2
3
401
11
2a
dtype:object
可以看到None和NaN都会替换成了1
In[10]:
Python
1
s.map({NaN:1,'a':'a'})
Out[10]:
Python
1
2
3
401
11
2a
dtype:object
同样None和NaN都会替换成了1
In[11]:
Python
1
s.map({NaN:2,'None':1,'a':'a'})
Out[11]:
Python
1
2
3
402
12
2a
dtype:object
将None替换成1的要求被忽略了
In[12]:
Python
1
s.map({'None':1,NaN:2,'a':'a'})
Out[12]:
Python
1
2
3
402
12
2a
dtype:object
将NaN替换成1的要求被忽略了
总结: 用Series.map对None进行替换时,会“顺便”把NaN也一起替换掉;NaN也会顺便把None替换掉。
如果None和NaN分别定义了不同的映射数值,那么只有一个会生效。
Series.replace中的表现
In[13]:
Python
1
2
s=Series([None,NaN,'a'])
s
Out[13]:
Python
1
2
3
40None
1NaN
2a
dtype:object
In[14]:
Python
1
s.replace([NaN],9)
Out[14]:
Python
1
2
3
409
19
2a
dtype:object
In[15]:
Python
1
s.replace([None],9)
Out[15]: