Scipy圆方差

时间:2018-10-17 13:35:16

标签: python numpy scipy statistics

根据我的理解,循环方差的范围在0到1之间。这在wikipediahere中也得到了证实。但是由于某些原因,来自scipy.stats的圆方差函数给出的值大于1。

import numpy as np
from scipy.stats import circmean, circvar

a = np.random.randint(0, high=360, size=10)

print(a)
print(circmean(a, 0, 360))
print(circvar(np.deg2rad(a)))
[143 116 152 172 349 152 182 306 345  81]
135.34974541954665
2.2576538466653857

有人可以告诉我为什么我从函数circvar中获取大于1的值

4 个答案:

答案 0 :(得分:7)

最没有帮助的答案是,因为那是scipy定义的方式,因此您最好要求开发人员获得明确的答案。 真。文档中的示例是

original-commit

所以您不能说该行为是意外的。 但是为什么要这样做呢?

您的第二个链接将一组n个角度a_1,... a_n的圆方差定义为

  

V = 1 − \ hat {R_1}

哪里

  

\ hat {R_1} = R_1 / n   R_1 = \ sqrt {C ^ 2 + S ^ 2}

  

C = \ sum_ {i = 1} ^ n cos(a_i)   S = \ sum_ {i = 1} ^ n sin(a_i)

scipy库通过

找到循环方差
from scipy.stats import circvar
circvar([0, 2*np.pi/3, 5*np.pi/3])
2.19722457734

要理解这有点棘手。 如果我们假设样本为零均值,范围为[0,2 * pi],并且使用默认轴(在示例中均为true),则可以简化为

ang = (samples - low)*2.*pi / (high - low)
S = sin(ang).mean(axis=axis)
C = cos(ang).mean(axis=axis)
R = hypot(S, C)
return ((high - low)/2.0/pi)**2 * 2 * log(1/R)

因此scipy使用的定义将R转换为2 * log(1 / R),而不是1-R。 好像很奇怪 回顾历史https://github.com/scipy/scipy/blame/v1.1.0/scipy/stats/morestats.py#L2696-L2733,有一次统计数据是使用

S = mean(sin(samples))
C = mean(cos(samples))
R = hypot(S, C)
V = 2 * log(1/R)

这似乎与您提供的定义一致。 在添加测试的同时,在一个错误修正中对此进行了更改,但未提及新计算的来源。

可以在https://github.com/scipy/scipy/pull/5747上找到有关scipy错误跟踪器的一些讨论。 这表明该行为是故意的,不会被修复。 http://docs.astropy.org/en/stable/api/astropy.stats.circvar.html还提供了另一种可以节省费用的实施方式,该实现请注意

  

此处使用的定义与scipy.stats.circvar中的定义不同。精确地,Scipy circvar使用基于小角度极限的近似值,该近似值接近线性方差。

因此,总而言之,出于未知原因,ang = (samples - low)*2*pi / (high-low) res = stats.mean(exp(1j*ang)) V = 1-abs(res) return ((high-low)/2.0/pi)**2 * V 使用了一个近似值(在某些情况下似乎很差)。但是,由于向后兼容,它不会被修复,因此您可能要使用scipy的实现。

答案 1 :(得分:1)

可能不应该。 circstd的计算看起来很正常:

return ((high - low)/2.0/pi) * sqrt(-2*log(R))

尽管circvar的计算看起来有误:

return ((high - low)/2.0/pi)**2 * 2 * log(1/R)

我不知道为什么将循环方差计算为2*ln(1/R)。这可能是我以前从未见过的近似值,但我不知道-我可能为此打开了一个错误。

答案 2 :(得分:1)

我开发了这段代码,它总是给我0-1之间的差异。刚刚改写了我读过的here

def variance_angle(deg):
    """
    deg: angles in degrees 
    """
    deg = np.deg2rad(deg)
    deg = deg[~np.isnan(deg)]

    S = np.array(deg)
    C = np.array(deg)

    length = C.size

    S = np.sum(np.sin(S))
    C = np.sum(np.cos(C))
    R = np.sqrt(S**2 + C**2)
    R_avg = R/length
    V = 1- R_avg

    return V

答案 3 :(得分:1)

根据文档字符串此circvar

  

...使用圆方差的定义,该定义在较小的范围内   角度返回接近“线性”方差的数字。

实际上,这是维基百科所说的circstd的平方

  

...的值介于0和无穷大之间。本标准的定义   偏差...非常有用,因为对于包裹正态分布而言,   是基础法线的标准偏差的估计量   分配。因此,它将允许循环分布为   与线性情况下一样标准化,适用于较小的标准值   偏差。这也适用于von Mises分布...

它还提到对于小点差,循环方差的两个定义是相同的,直到因数为2。