根据我的理解,循环方差的范围在0到1之间。这在wikipedia和here中也得到了证实。但是由于某些原因,来自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的值
答案 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。