不太有帮助的答案是因为这是scipy的定义方式,所以你最好问开发者得到一个明确的答案。文档中的例子如下:
from scipy.stats import circvar
circvar([0, 2*np.pi/3, 5*np.pi/3])
2.19722457734
所以你不能说这种行为是出乎意料的。
但是为什么要那样做呢?
你提供的第二个链接定义了一组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库通过以下方式计算循环方差:
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)
这有点难以理解。如果我们假设样本是零均值的,范围为[0,2*pi],并且使用默认轴(在示例中全部为真),则可以简化为:
S = mean(sin(samples))
C = mean(cos(samples))
R = hypot(S, C)
V = 2 * log(1/R)
因此,scipy使用2*log(1/R)而不是1-R来转换R。这似乎很奇怪。通过查看历史记录https://github.com/scipy/scipy/blame/v1.1.0/scipy/stats/morestats.py#L2696-L2733,可以看到一度计算统计数据时使用的方式。
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的bug跟踪器上有一些讨论可用于
https://github.com/scipy/scipy/pull/5747,它表明这种行为是有意的,并且不会修复。 Astropy还提供另一个实现,
http://docs.astropy.org/en/stable/api/astropy.stats.circvar.html,其中注意到:
这里使用的定义与scipy.stats.circvar中使用的定义不同。精确地说,Scipy circvar使用基于小角度极限的近似方法,该近似方法逼近线性方差。
因此,总之,由于某种未知原因,scipy使用了一种近似方法(在某些情况下似乎相当糟糕)。 但是,由于向后兼容性,它将不会被修复,因此您可能希望使用astropy的实现。
var
只是std
的平方。我并不是说这是否适用于此处。文档字符串说:“这使用了一个圆形方差的定义,在小角度极限下返回一个接近于‘线性’方差的数字。” 这正是维基百科关于std
的说法 - 所以我认为这看起来没问题。 - Paul Panzer1 - R
更改为2 * log (1/r)
,所以那个人可能知道。 - CJR