C#、数値計算 - データ値の連続ストリームから任意の分位数を推定するための計算方法とソース プログラム

1 分位数Quantile

分位点 (Quantile) は、分位点とも呼ばれ、確率変数の確率分布範囲をいくつかの等しい部分に分割する数値点、パーセンタイルなどを指します。

2 一般的な分位数の種類

2.1 二分位数

有限の数値セットの場合、すべての観測値を高いものから低いものに並べ替えることで、中央の値を中央値として見つけることができます。観測値が偶数の場合、中央値は一意ではなく、通常は中央の 2 つの値の平均が中央値、つまり 2 進分位数として採用されます。
数値セット内の値の最大半分は中央値より小さく、値の最大半分は中央値より大きくなります。中央値より大きい値と半分より小さい値が半分未満の場合は、セット内に中央値と等しい値が存在する必要があります。
限られた数のデータの二分位数を計算する方法は、すべての同じデータをサイズの順に並べることです。データ数が奇数の場合は中央のデータがデータ群の中央値となり、データ数が偶数の場合は中央の 2 つのデータの算術平均がデータ群の中央値となります。

2.2 四分位数

四分位とは統計学における分位の一種で、すべての値を小さいものから大きいものまで並べて4等分し、3つの分割点の値が四分位となります。
1) 「小さい四分位」とも呼ばれる最初の四分位 (Q1) は、サンプル内のすべての値を小さいものから大きいものへと並べた 25 番目の百分位数に等しい; 2) 第 2 四分位 (Q2) とも呼ば
れる「中央値」として、小さいものから大きいものまで並べられたサンプル内のすべての値の 50% の数値に等しい;
3) 3 番目の四分位数 (Q3)、「大きい四分位数」とも呼ばれ、75 番目の百分位数に等しいサンプル内のすべての値を小さいものから大きいものまで並べた後の数値。
第 3 四分位数と第 1 四分位数の差は、四分位間範囲とも呼ばれます。

2.3パーセンタイル

パーセンタイル (統計用語)。データのセットが小さいものから大きいものに並べ替えられ、対応する累積パーセンタイルが計算される場合、特定のパーセンタイルに対応するデータの値は、このパーセンタイル桁のパーセンタイルと呼ばれます。学力テストのスコアなどの教育統計で使用される場合、これは PR 値と呼ばれます。

3 分位数の適用

分位回帰のアイデアが提案されてから 30 年近くが経過し、30 年近くの開発を経て、分位回帰は理論と手法がますます成熟し、さまざまな分野で広く使用されています。線形モデルであろうと非線形モデルであろうと、分位点回帰は優れたツールであり、一般的な回帰モデルを補足するのに役立ちます。

分位点回帰は、古典的な条件付き平均モデルに基づく最小二乗法の拡張であり、いくつかの分位点関数を使用してモデル全体を推定します。分位点回帰法の特殊なケースは中央値回帰 (最小乗算回帰) であり、これは対称重みを使用して残差最小化の問題を解決しますが、他の条件付き分位点回帰では残差最小化の問題を解決するために非対称重みを使用する必要があります [2] 。

分位回帰では、残差の絶対値の合計を重み付けしてパラメータを推定する方法が使用され、その利点は次の側面に反映されます。 まず、モデル内のランダムな外乱項目の分布について仮定を行う必要がありません。 、そのため、回帰モデル全体が大きな強い堅牢性を持ちます。第 2 に、分位回帰自体は、従属変数の平均と分散の間の関係を記述するために接続関数を使用しないため、分位回帰は比較的良好な弾性特性を持ちます。第 3 に、分位回帰はすべての分位数に対して実行されるため、データ内の外れ値に耐性があります。第 4 に、通常の最小二乗回帰とは異なり、分位数回帰では従属変数が単調に変換されます。最後に、分位数回帰によって推定されたパラメーターは、次の条件の下で漸近的な良好性を持ちます。大サンプル理論。

4 分位数を計算するための C# ソース プログラム

システムを使用する;

namespace Legalsoft.Truffer
{     /// <summary>     /// データ値の連続ストリームから /// 任意の分位値を推定するためのオブジェクト      。     /// </summary>     public class IQagent     {         public const int nbuf = 1000;         private int nq { 取得; セット; プライベート         int nt {取得; セット; プライベート         int nd {取得; セット; プライベート         ダブル[] pval {取得; セット; プライベート         ダブル[] dbuf;         private double[] qile { get; セット; プライベート         ダブルq0 {取得; セット; プライベート         ダブルqm {取得; セット; }














        public IQagent()
        {             this.nq = 251;             this.nt = 0;             this.nd = 0;             this.pval = 新しい double[nq];             this.dbuf = 新しい double[nbuf];             this.qile = 新しい double[nq];             this.q0 = 1.0e99;             this.qm = -1.0e99;







            for (int j = 85; j <= 165; j++)
            {                 pval[j] = (j - 75.0) / 100.0;             }

            // 1.0e-6 から 1~1.0e-6 の範囲の p - 値の汎用配列を設定します。
            // 必要に応じてこれを変更できます。
            for (int j = 84; j >= 0; j--)
            {                 pval[j] = 0.87191909 * pval[j + 1];                 pval[250 - j] = 1.0 - pval[j];             }         }



        /// <summary>
        /// ストリームから新しい値を取り込みます。
        /// </summary>
        /// <param name="datum"></param>
        public void add(double datum)
        {             dbuf[nd++] = datum;             if (データ < q0)             {                 q0 = データ;             if             (データ > qm)             {                 qm = データ;             if             (nd == nbuf)             {                 update();             }         }













        /// <summary>
        /// バッチ更新。         /// この関数は add または report によって呼び出されます。 /// ユーザーが
        直接呼び出すことはできません。         /// </summary>         public void update()         {             int jd = 0;             int jq = 1;             ダブルテルド = 0.0;             ダブル tnew = 0.0;             double[] newqile = 新しい double[nq];








            Sorter.sort(dbuf, nd);

            ダブルqold = q0;
            ダブルqnew = q0;
            qile[0] = newqile[0] = q0;
            qile[nq - 1] = newqile[nq - 1] = qm;
            pval[0] = Math.Min(0.5 / (nt + nd), 0.5 * pval[1]);
            pval[nq - 1] = Math.Max(1.0 - 0.5 / (nt + nd), 0.5 * (1.0 + pval[nq - 2]));
            for (int iq = 1; iq < nq - 1; iq++)
            {                 double target = (nt + nd) * pval[iq];                 if (tnew < target)                 {                     for (; ; )                     {                         if (jq < nq && (jd >= nd || qile[jq] < dbuf[jd]))                         {







                            qnew = qile[jq];
                            tnew = jd + nt * pval[jq++];
                            if (tnew >= ターゲット)
                            {                                 ブレーク;                             }                         }                         else                         {                             qnew = dbuf[jd];                             tnew = 言われた;                             if (qile[jq] > qile[jq - 1])                             {                                 tnew += nt * (pval[jq] - pval[jq - 1]) * (qnew - qold) / (qile[jq] - qile[jq - 1]);                             }











                            jd++;
                            if (tnew >= ターゲット)
                            {                                 ブレーク;                             = tnew++;                             }                             qold = qnew;                             if (tnew >= ターゲット)                             {                                 ブレーク;                             }                         }                         伝えられた = tnew;                         qold = qnew;                     }                 }                 //if (tnew == 伝えられた)














                if (Math.Abs​​(tnew - テルド) <= float.Epsilon)
                {                     newqile[iq] = 0.5 * (qold + qnew);                 }                 else                 {                     newqile[iq] = qold + (qnew - qold) * (ターゲット - 伝えられた) / (tnew - 伝えられた);                 伝え                 られた = tnew;                 qold = qnew;             }             // qile = newqile;             qile = Globals.CopyFrom(newqile);             nt += nd;             nd = 0;         }













        /// <summary> ///         これまでに確認されたデータの
        推定 p 分位数を /// 返します 。
(例: 中央値の場合は p D 0:5。)
        /// </summary>
        /// <param name="p"></param>
        /// <returns></returns>
        public double report(double p )
        {             if (nd > 0)             {                 update();             int             jl = 0;             int jh = nq - 1;             int j;             while (jh - jl > 1)             {                 j = (jh + jl) >> 1;                 if (p > pval[j])                 {












                    jl = j;
                }
                else
                {                     jh = j;                 j =             jl             ;             double q = qile[j] + (qile[j + 1] - qile[j]) * (p - pval[j]) / (pval[j + 1] - pval[j]);             return Math.Max(qile[0], Math.Min(qile[nq - 1], q));         } }     }









 

おすすめ

転載: blog.csdn.net/beijinghorn/article/details/132051681