正常情况下,numpy.var()
与numpy.nanvar()
不同,但numpy.std()
和numpy.nanstd()
相同。但是:
df = pd.DataFrame({'A': [1,2,3,4,5,6,7,8,9,10,np.NaN,np.NaN,np.NaN]})
print("np.var() " + " : "+ str(np.var(df["A"])))
print("np.nanvar() " + " : "+ str(np.nanvar(df["A"])))
print("np.std() " + " : "+ str(np.std(df["A"])))
print("np.nanstd() " + " : "+ str(np.nanstd(df["A"])))
结果:
np.var() : 8.25
np.nanvar() : 8.25
np.std() : 2.8722813232690143
np.nanstd() : 2.8722813232690143
为什么两者都一样? np.var()
或np.std()
的文档中没有任何关于缺失值的内容。
答案 0 :(得分:7)
这是因为numpy.std
(resp。numpy.var
)尝试委托第一个参数的std
(resp。var
)方法,如果它不是ndarray(来自source code here):
def std(a, axis=None, dtype=None, out=None, ddof=0, keepdims=np._NoValue):
kwargs = {}
if keepdims is not np._NoValue:
kwargs['keepdims'] = keepdims
if type(a) is not mu.ndarray:
try:
std = a.std
except AttributeError:
pass
else:
return std(axis=axis, dtype=dtype, out=out, ddof=ddof, **kwargs)
return _methods._std(a, axis=axis, dtype=dtype, out=out, ddof=ddof,
**kwargs)
所以,你只需要调用pandas.Series.std
(0自由度)。在Pandas库中,所有描述性统计函数都处理缺失值(从文档中可以看到Calculations with missing data)。
这里要说的是,如果您拥有Pandas系列,那么首先使用Pandas数据类型方法而不是NumPy自由函数会更加清晰。
这种行为是NumPy为许多函数所做的事情,它们使用类似数组的对象作为第一个参数 - 尝试在对象上使用相同的方法(如果存在),如果不使用某些回退。但情况并非总是如此 - 例如
>>> a = np.random.randint(0, 100, 5)
>>> a
array([49, 68, 93, 51, 94])
>>> np.sort(a) # not in-place
array([49, 51, 68, 93, 94])
>>> a
array([49, 68, 93, 51, 94])
>>> a.sort() # in-place
>>> a
array([49, 51, 68, 93, 94])
此外,在大多数情况下,nanfunctions.py
中的NaN处理函数首先调用_replace_nan
,将您的类型转换为ndarray,并将ndarray中的NaN值替换为不会影响的值无论他们执行什么计算(即np.nansum
用0替换NaN,np.nanprod
用1替换NaNs。然后他们打电话给他们的非NaN同行进行实际计算。 (例如:np.nansum
)
def nansum(a, axis=None, dtype=None, out=None, keepdims=np._NoValue):
a, mask = _replace_nan(a, 0)
return np.sum(a, axis=axis, dtype=dtype, out=out, keepdims=keepdims)
例如,在Pandas系列上调用np.nansum
,实际上并没有使用pandas.Series.sum
,因为系列首先被转换为_replace_nan
内的ndarray。所以不要(我不确定你为什么会这样)假设或依赖你系列的sum
方法。
# a silly example
>>> s = pd.Series([1, 2, 3, np.nan])
>>> s.sum = lambda *args, **kwargs: "instance sum"
>>> s.sum()
'instance sum'
>>> np.sum(s)
'instance sum'
>>> np.nansum(s)
6