Python 圆方差
根据我的理解,循环方差的范围在0到1之间。这一点在中也得到了证实。但由于某些原因,Python 圆方差,python,numpy,scipy,statistics,Python,Numpy,Scipy,Statistics,根据我的理解,循环方差的范围在0到1之间。这一点在中也得到了证实。但由于某些原因,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
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的值,这可能是不应该的。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)
。这可能是我以前从未见过的近似值,但我不知道-我可能会为此打开一个bug。不太有用的答案是,因为scipy就是这样定义的,所以你最好让开发人员得到一个明确的答案。
真正地文档中的示例是
from scipy.stats import circvar
circvar([0, 2*np.pi/3, 5*np.pi/3])
2.19722457734
所以你不能说这种行为是未经允许的。
但为什么要这样做呢
第二个链接定义了一组n个角度a_1。。。作为
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使用的定义将R转换为2*log(1/R),而不是1-R。
这似乎很奇怪。
纵观历史,有一次统计数据是使用
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跟踪器的一些讨论可在以下站点获得。
这表明这种行为是故意的,不会被纠正。
astropy中还有另一个可用的实现
此处使用的定义与scipy.stats.circvar中的定义不同。准确地说,Scipy circvar使用了一种基于小角度极限的近似方法,该方法接近线性方差
因此,总之,出于未知原因,
scipy
使用了近似值(在某些情况下,这似乎相当糟糕)。但是,由于向后兼容,它不会被修复,因此您可能希望使用astropy的实现。我开发了这段代码,它总是给我0-1之间的差异。只是改编了我读的东西
此
circvar
根据docstring
。。。使用循环方差的定义,该定义在小范围内
角度返回一个接近“线性”方差的数字
事实上,它是维基百科所说的circstd
的平方
。。。值介于0和无穷大之间。这是标准的定义
偏离非常有用,因为对于包裹正态分布
是基础正态分布标准差的估计量
分配。因此,它将允许循环分发
标准化,如线性情况,用于标准的小值
偏离这也适用于冯·米塞斯分布
它还提到,对于小差价,循环方差的两个定义是相同的,最多为两个因子。这
var
只是std
的平方。我不是说这在这里是或是不合适的。Docstring说“这使用了一个循环方差的定义,在小角度的限制下返回一个接近‘线性’方差的数字。”这就是维基百科关于std
-的说法,所以我觉得这很好。是拉动请求,其中方差计算从1-R
更改为2*log(1/R)
,以便guy知道。@CJ59,这家伙是numpy和scipy软件包的创始人!
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