在Pandas类型

时间:2018-04-15 20:36:10

标签: python pandas numpy statistics

正常情况下,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()的文档中没有任何关于缺失值的内容。

1 个答案:

答案 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