算法 A 求稳健平均值和稳健标准差
Posted zhuo木鸟
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了算法 A 求稳健平均值和稳健标准差相关的知识,希望对你有一定的参考价值。
算法原理
算法 A 来自 GB/T 6379.5。应用此算法计算得到数据平均值和标准差的稳健值。稳健性是估计算法的特点,而不是其产生的估计值的特点,因此严格来说,称由此算法计算的平均值和标准差是稳健的是不确切的。然而,为避免使用繁琐的术语,“稳健均值”和“稳健标准差”应理解为利用稳健算法计算的总体均值和总体标准差的均值估计。
设数据为
x
i
,
i
∈
(
1
,
2
,
⋯
,
n
)
x_i, i\\in(1,2,\\cdots,n)
xi,i∈(1,2,⋯,n),记稳健平均值为
x
∗
,
s
∗
x^*, s^*
x∗,s∗,首先是计算初始值:
x
∗
=
med
x
i
s
∗
=
1.483
×
med
∣
x
i
−
x
∗
∣
\\begin{array}{c} x^{*}=\\operatorname{med} x_{i} \\\\ s^{*}=1.483 \\times \\operatorname{med}\\left|x_{i}-x^{*}\\right| \\end{array}
x∗=medxis∗=1.483×med∣xi−x∗∣
对每个
x
i
x_i
xi,有:
x
i
∗
=
{
x
∗
−
δ
,
若
x
i
<
x
∗
−
δ
x
∗
+
δ
,
若
x
i
>
x
∗
+
δ
x
i
,
其他
x_{i}^{*}=\\left\\{\\begin{array}{cc} x^{*}-\\delta, & \\text { 若 } x_{i}<x^{*}-\\delta \\\\ x^{*}+\\delta, & \\text { 若 } x_{i}>x^{*}+\\delta \\\\ x_{i}, & \\text { 其他 } \\end{array}\\right.
xi∗=⎩⎨⎧x∗−δ,x∗+δ,xi, 若 xi<x∗−δ 若 xi>x∗+δ 其他
其中:
δ
=
1.5
s
∗
\\delta=1.5 s^{*}
δ=1.5s∗,再次计算:
x
∗
=
∑
x
i
∗
/
p
s
∗
=
1.134
∑
(
x
i
∗
−
x
∗
)
2
/
(
p
−
1
)
\\begin{array}{c} x^{*}=\\sum x_{\\mathrm{i}}^{*} / p \\\\ s^{*}=1.134 \\sqrt{\\sum\\left(x_{\\mathrm{i}}^{*}-x^{*}\\right)^{2} /(p-1)} \\end{array}
x∗=∑xi∗/ps∗=1.134∑(xi∗−x∗)2/(p−1)
重复:
x
i
∗
=
{
x
∗
−
δ
,
若
x
i
<
x
∗
−
δ
x
∗
+
δ
,
若
x
i
>
x
∗
+
δ
x
i
,
其他
x_{i}^{*}=\\left\\{\\begin{array}{cc} x^{*}-\\delta, & \\text { 若 } x_{i}<x^{*}-\\delta \\\\ x^{*}+\\delta, & \\text { 若 } x_{i}>x^{*}+\\delta \\\\ x_{i}, & \\text { 其他 } \\end{array}\\right.
xi∗=⎩⎨⎧x∗−δ,x∗+δ,xi, 若 xi<x∗−δ 若 xi>x∗+δ 其他
直到 s ∗ s^* s∗ 的 第三位有效数字和 x ∗ x^* x∗ 的对应数字在连续两次迭代中不变。
代码
# -*- coding: utf-8 -*-
import pandas as pd
import numpy as np
def location_corresponding(x_str, s_str):
'''
s 的第三位有效数字,以及对应 x 的相应的数字
'''
digit_location = s_str.find('.')
if digit_location >= 3:
# 如果小数点在字符串的第 4 位或大于第四位,也即数字至少在 100 以上
# 此时第三位有效数字,肯定在小数点前。
significant_num = s_str[2]
# 有效位数于小数点的相对位置
# 0 代表在小数点前, 3-1 是指从小数点前数起的位数
str_len = len(s_str[:digit_location])
sig_loc = (0, str_len-3-1)
elif s_str[0] == '0':
# 若整数部分是0,则有效数字的位置在小数点后
s_without_int = s_str[digit_location:]
while '0' in s_without_int:
s_without_int = s_without_int.replace('0', '')
digit_location += 1
significant_num = s_str[digit_location+3]
# 1 表示有效数字在小数点后
sig_loc = (1, 3)
elif digit_location == -1 and len(s_str) >= 3:
# 若只有整数,没有小数部分
str_len = len(s_str)
sig_loc = (0, str_len-3)
significant_num = s_str[2]
elif digit_location == -1 and len(s_str) < 3:
significant_num = '0'
else:
# 若整数部分小于 2 位,则
sig_loc = (1, 3-digit_location)
#
significant_num = s_str[sig_loc[1]+digit_location]
# x 对应的数字
x_digit_location = x_str.find('.')
if sig_loc[0] == 0:
if x_digit_location == -1 and len(x_str) >= 3:
x_significant_num = x_str[2]
elif x_digit_location == -1 and len(x_str) < 3:
x_significant_num = '0'
else:
x_significant_num = x_str[x_digit_location-sig_loc[1]]
print(sig_loc[1])
print('前')
else:
x_significant_num = x_str[x_digit_location+sig_loc[1]]
return x_significant_num, significant_num
def coverage_critiria(x_list, s_list):
'''
收敛准则
其中 s_list 是一个长度为 3 的 list, 包含当前迭代的 s* 和之前两个迭代的 s*
其中 x_list 也一样
难点在于:如何找出 s 的第三位有效数字,对应 x 的数位呢?
这里的解决办法是:找出 s 三位有效数字,在小数点的位置,从而应用于 x 中
'''
s_numbers = []
x_numbers = []
for i in range(3):
s = s_list[i]
# s 的字符串
s_str = str(s)
x = x_list[i]
# x 的字符串
x_str = str(x)
x_sig_num, s_sig_num = location_corresponding(x_str, s_str)
s_numbers.append(s_sig_num)
x_numbers.append(x_sig_num)
s_equal_flag = (s_numbers[0] == s_numbers[1]) and (s_numbers[0] == s_numbers[2])
x_equal_flag = (x_numbers[0] == x_numbers[1]) \\
and (x_numbers[0] == x_numbers[2])
if s_equal_flag and x_equal_flag:
return True
else:
return False
def perform_algorithm_A(x):
'''
x 是一个向量
'''
if type(x) is list:
x = np.array(x)
# 稳健平均和稳健标准差初始值
x_star = np.median(x)
x_diff = np.absolute(x-x_star)
s_star = 1.483*np.median(x_diff)
#
delta = 1.5*s_star
higher_bound = x_star + delta
lower_bound = x_star - delta
x_list = []
s_list = []
while True:
x[x>higher_以上是关于算法 A 求稳健平均值和稳健标准差的主要内容,如果未能解决你的问题,请参考以下文章
Trimmed 稳健均值估计与 中位数-中位数配对偏差法估计标准差——理论与 Python 实现