算法 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×medxix
对每个 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(xix)2/(p1)

重复:
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 求稳健平均值和稳健标准差的主要内容,如果未能解决你的问题,请参考以下文章

Q 方法求稳健标准差——理论和 Python实现

Q 方法求稳健标准差——理论和 Python实现

Trimmed 稳健均值估计与 中位数-中位数配对偏差法估计标准差——理论与 Python 实现

Trimmed 稳健均值估计与 中位数-中位数配对偏差法估计标准差——理论与 Python 实现

简单稳健估计法——原理与 Python 实现

简单稳健估计法——原理与 Python 实现