我參加本月挑戰的動機是讓您超越傳統的異常值定義,將其視為遠離數據中心的觀察值(相對於數據可變性的數量)。 通常,我們可以將異常值視為不具有代表性的數據點,它不屬於其餘數據。 這才是真正的挑戰:我們如何定義代表性? 我在下面提供的方法是我對這個問題的看法。
下面的算法根據點之間的距離將觀察分為相似和不同的集合。 與聚類的標準凝聚方法不同,從一組開始。 將分割點定義為距離最遠的觀測值的中間值,前提是它們的距離超過 75 個觀測值之間的差值的三倍日所有非零距離的分位數和中位數(距離傳播)。 如果沒有切點,則停止。 否則,用兩個新組替換現有組。 對每個新組重複上述過程,使用新組或整個數據集的距離傳播,以較大者為準。 繼續直到沒有組包含切割點。
findOutliers = Function({vals},{Default Local},
q1 = 3; //Spread Multiplier
q2 = 0.75; //Quantile to define upper bound of spread
distSpread = 0;
nMissing = 0;
tmpTbl = New Table("tmp",New Column("C1",Values(vals)),Private);
sumTbl = tmpTbl << Summary(Group(:C1),Private);
vals = Column(sumTbl,1) << Get Values;
freqs = Column(sumTbl,2) << Get Values;
If(N Row(Loc(vals)) == 1, Return([]));
Close(tmpTbl,No Save);
If(Is Missing(vals[1]),
nMissing = freqs[1];
freqs = freqs[2::N Row(vals)];
vals = vals[2::N Row(vals)];
);
vals = Sort Ascending(vals[Loc Nonmissing(vals)]);
groups = Eval List({vals});
cutPoints = [];
While(N Items(groups) > 0,
newGroups = {};
For Each({nextVals},groups,
distances = nextVals[2::N Row(nextVals)] - nextVals[1::(N Row(nextVals)-1)];
distSpread = Max(distSpread,Median(distances[Loc(distances>0)]) + q1*(Quantile(q2,distances[Loc(distances>0)]) - Median(distances[Loc(distances>0)])));
maxDist = Maximum(distances);
If(maxDist>distSpread,
cutID = Loc(distances==maxDist)[1];
cutPoints |/= (nextVals[cutID+1]+nextVals[cutID])/2;
If(cutID == 1,
Insert Into(newGroups,nextVals[2::N Row(nextVals)]),//ELSE
If(cutID == N Row(distances),
Insert Into(newGroups,nextVals[1::cutID]),
//ELSE
Insert Into(newGroups,nextVals[1::cutID]);
Insert Into(newGroups,nextVals[(cutID+1)::N Row(nextVals)]);
)
)
);
);
groups = newGroups;
);
cutPoints = Sort Ascending(cutPoints);
cutPoints;
);
首先,需要一些內務處理來繞過具有單個值的數據。 根據來自的結果挑戰 9 ,我正在使用摘要同時查找數據中的唯一值並對其進行排序。 通過將向量偏移一併取其差來找到距離。 該算法通過收集切割點並丟棄沒有切割點的組來進行。 這一直持續到沒有組剩下。
該算法相當快,大約需要 1.6 秒來處理所有數據列探測我機器上的示例數據數據表。 在算法的頂部,我添加了兩個變量,讓您更改 3x 乘數和 75日分位數。 在下面附加的腳本中,挑戰 11 異常值篩選,我添加了一些額外的窗口裝飾來提供一些界面,允許列選擇和生成包含摘要信息和直方圖的報告窗口,並將切割點繪製為參考線。
我將從 JMP 挑戰賽中稍作休息,以從事另一個腳本項目。 我將為小型項目整理書面說明和視頻,以幫助新用戶和中級用戶提高他們的 JSL 技能。 我將專注於常見操作,例如將表放在一起、訪問來自多個源的數據、構建自定義報告等。 我還將嘗試研究一些更高級的東西,比如表達式處理和模式匹配。 如果您認為有任何有價值的內容,請在此處發布,或向我發送社區消息或電子郵件( don.mccormack@jmp.com )。