loading...

08 December 2024
Outlier Correction
LAMBDA Formula · LAMBDA Formula (Exclude Seasonality) · Excel VBA UDF

Here is my Office 365 LAMBDA Excel Formula that can be used to perform Outlier Correction on a range of values including the use of a fence coefficient (test function taking a range and a double value) Back · Purchase

 
1
2
3
4
5
6
7
=LAMBDA(ARRAY,FENCE,LET(
        QTL_1,QUARTILE.INC(ARRAY,1),
        QTL_3,QUARTILE.INC(ARRAY,3),
        IQR,QTL_3-QTL_1,
        LOWER,QTL_1-FENCE*(IQR),
        UPPER,QTL_3+FENCE*(IQR),
        RESULT,IF(ARRAY>UPPER,UPPER,IF(ARRAY<LOWER,LOWER,ARRAY)),RESULT))($J$16:$X$16,1.5)
 
 
=LAMBDA(ARRAY,FENCE,LET(
        QTL_1,QUARTILE.INC(ARRAY,1),
        QTL_3,QUARTILE.INC(ARRAY,3),
        IQR,QTL_3-QTL_1,
        LOWER,QTL_1-FENCE*(IQR),
        UPPER,QTL_3+FENCE*(IQR),
        RESULT,IF(ARRAY>UPPER,UPPER,IF(ARRAY<LOWER,LOWER,ARRAY)),RESULT))($J$16:$X$16,1.5)

Add a Named Range called OutlierCorrection.Quartile and then Copy & Paste the formula below:

 
1
2
3
4
5
6
7
=LAMBDA(ARRAY,FENCE,LET(
        QTL_1,QUARTILE.INC(ARRAY,1),
        QTL_3,QUARTILE.INC(ARRAY,3),
        IQR,QTL_3-QTL_1,
        LOWER,QTL_1-FENCE*(IQR),
        UPPER,QTL_3+FENCE*(IQR),
        RESULT,IF(ARRAY>UPPER,UPPER,IF(ARRAY<LOWER,LOWER,ARRAY)),RESULT))
 
 
=LAMBDA(ARRAY,FENCE,LET(
        QTL_1,QUARTILE.INC(ARRAY,1),
        QTL_3,QUARTILE.INC(ARRAY,3),
        IQR,QTL_3-QTL_1,
        LOWER,QTL_1-FENCE*(IQR),
        UPPER,QTL_3+FENCE*(IQR),
        RESULT,IF(ARRAY>UPPER,UPPER,IF(ARRAY<LOWER,LOWER,ARRAY)),RESULT))

Use the Function like this in any Worksheet in Excel for a range of any size ($J$16:$X$16 are the actuals, 1.5 is the fence):

 
1
=OutlierCorrection.Quartile($J$16:$X$16,1.5)
 
 
=OutlierCorrection.Quartile($J$16:$X$16,1.5)

Chart demonstrating the LAMBDA Outlier Correction Function on a range of 15 values with a FENCE of 1.5





Here is my Office 365 LAMBDA Excel Formula that can be used to perform Outlier Correction on a range of values including the use of a fence coefficient (test function taking a range and a double value) as well as a PERIODS range and an EXCLUDE comma-delimited list of seasonal periods to exclude from the algorithm Back · Purchase

 
1
2
3
4
5
6
7
8
9
=LAMBDA(ARRAY,FENCE,PERIODS,EXCLUDE,LET(
        QTL_1,QUARTILE.INC(ARRAY,1),
        QTL_3,QUARTILE.INC(ARRAY,3),
        IQR,QTL_3-QTL_1,
        LOWER,QTL_1-FENCE*(IQR),
        UPPER,QTL_3+FENCE*(IQR),
        EXCLUDEPERIODS,IF(ISNUMBER(SEARCH(","&PERIODS&",",","&EXCLUDE&",")),PERIODS),
        RESULT,IF(ARRAY>UPPER,IF(PERIODS<>EXCLUDEPERIODS,UPPER,ARRAY),
        IF(ARRAY<LOWER,IF(PERIODS<>EXCLUDEPERIODS,LOWER,ARRAY),ARRAY)),RESULT))($D$28:$R$28,1.5,$D27:$R27,$L$22)
 
 
=LAMBDA(ARRAY,FENCE,PERIODS,EXCLUDE,LET(
        QTL_1,QUARTILE.INC(ARRAY,1),
        QTL_3,QUARTILE.INC(ARRAY,3),
        IQR,QTL_3-QTL_1,
        LOWER,QTL_1-FENCE*(IQR),
        UPPER,QTL_3+FENCE*(IQR),
        EXCLUDEPERIODS,IF(ISNUMBER(SEARCH(","&PERIODS&",",","&EXCLUDE&",")),PERIODS),
        RESULT,IF(ARRAY>UPPER,IF(PERIODS<>EXCLUDEPERIODS,UPPER,ARRAY),
        IF(ARRAY<LOWER,IF(PERIODS<>EXCLUDEPERIODS,LOWER,ARRAY),ARRAY)),RESULT))($D$28:$R$28,1.5,$D27:$R27,$L$22)

Add a Named Range called OutlierCorrection.Quartile.Exclude and then Copy & Paste the formula below:

 
1
2
3
4
5
6
7
8
9
=LAMBDA(ARRAY,FENCE,PERIODS,EXCLUDE,LET(
        QTL_1,QUARTILE.INC(ARRAY,1),
        QTL_3,QUARTILE.INC(ARRAY,3),
        IQR,QTL_3-QTL_1,
        LOWER,QTL_1-FENCE*(IQR),
        UPPER,QTL_3+FENCE*(IQR),
        EXCLUDEPERIODS,IF(ISNUMBER(SEARCH(","&PERIODS&",",","&EXCLUDE&",")),PERIODS),
        RESULT,IF(ARRAY>UPPER,IF(PERIODS<>EXCLUDEPERIODS,UPPER,ARRAY),
        IF(ARRAY<LOWER,IF(PERIODS<>EXCLUDEPERIODS,LOWER,ARRAY),ARRAY)),RESULT))
 
 
=LAMBDA(ARRAY,FENCE,PERIODS,EXCLUDE,LET(
        QTL_1,QUARTILE.INC(ARRAY,1),
        QTL_3,QUARTILE.INC(ARRAY,3),
        IQR,QTL_3-QTL_1,
        LOWER,QTL_1-FENCE*(IQR),
        UPPER,QTL_3+FENCE*(IQR),
        EXCLUDEPERIODS,IF(ISNUMBER(SEARCH(","&PERIODS&",",","&EXCLUDE&",")),PERIODS),
        RESULT,IF(ARRAY>UPPER,IF(PERIODS<>EXCLUDEPERIODS,UPPER,ARRAY),
        IF(ARRAY<LOWER,IF(PERIODS<>EXCLUDEPERIODS,LOWER,ARRAY),ARRAY)),RESULT))

Use the Function like this in any Worksheet in Excel for a range of any size ($D$28:$R$28 are the actuals, 1.5 is the fence, $D27:$R27 are the periods, $L$22 is a comma-delimited list of seasonal periods to exclude):

 
1
=OutlierCorrection.Quartile.Exclude($D$28:$R$28,1.5,$D27:$R27,$L$22)
 
 
=OutlierCorrection.Quartile.Exclude($D$28:$R$28,1.5,$D27:$R27,$L$22)

Chart demonstrating the LAMBDA Exclude Outlier Correction Function on a range of 15 values with a FENCE of 1.5, using 15 periods and a comma-delimited list of periods to exclude i.e. 4,12. Exclude periods can be WK49,WK50,WK51 etc. thereby preventing the cleaning of seasonal Weeks by the algorithm





Here is my VBA UDF for Excel that can be used to perform Outlier Correction on a range of values >0 with optional exclude time series periods and fence (very useful to prevent cleaning of seasonal periods). Copy & Paste this Code into any Standard Code Module Back · Purchase

 
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
Public Function QuartileOutlierCorrection(ByVal Known_ys As Range, ByVal Known_xs As Range, Optional ByVal Exclude_xs As String = vbNullString, Optional ByVal Fence As Double = 1) As Variant
     
    Dim X As Long
    Dim Y As Long
    Dim YS As Variant
    Dim XS As Variant
     
    YS = Known_ys
    XS = Known_xs
    For X = 1 To UBound(YS, 2)
        If YS(1, X) <> Empty Then YS(1, X) = Val(YS(1, X))
        If YS(1, X) <= 0 Then
            YS(1, X) = Empty
        End If
    Next X
     
    Dim Q1 As Double
    Dim Q3 As Double
    Dim IQR As Double
    Dim Lower As Double
    Dim Upper As Double
         
    On Error Resume Next
    Q1 = Application.WorksheetFunction.Quartile_Inc(YS, 1)
    Q3 = Application.WorksheetFunction.Quartile_Inc(YS, 3)
    IQR = Q3 - Q1
    Lower = Q1 - (Fence * IQR)
    Upper = Q3 + (Fence * IQR)
    On Error GoTo 0
 
    If Exclude_xs = vbNullString Then
        For X = 1 To UBound(YS, 2)
            If YS(1, X) <> Empty Then
                If YS(1, X) < Lower Then
                    YS(1, X) = Lower
                ElseIf YS(1, X) > Upper Then
                    YS(1, X) = Upper
                End If
            End If
        Next X
    Else
        On Error Resume Next
        Dim Match As Long
        For Y = 1 To UBound(XS, 2)
            Match = InStr(1, Exclude_xs, Left(XS(1, Y), 2), vbTextCompare)
            If Match = 0 Then
                X = Y
                If YS(1, X) <> Empty Then
                    If YS(1, X) < Lower Then
                        YS(1, X) = Lower
                    ElseIf YS(1, X) > Upper Then
                        YS(1, X) = Upper
                    End If
                End If
            End If
        Next Y
        On Error GoTo 0
    End If
     
    QuartileOutlierCorrection = YS
     
End Function
 
 
Public Function QuartileOutlierCorrection(ByVal Known_ys As Range, ByVal Known_xs As Range, Optional ByVal Exclude_xs As String = vbNullString, Optional ByVal Fence As Double = 1) As Variant
    
    Dim X As Long
    Dim Y As Long
    Dim YS As Variant
    Dim XS As Variant
    
    YS = Known_ys
    XS = Known_xs
    For X = 1 To UBound(YS, 2)
        If YS(1, X) <> Empty Then YS(1, X) = Val(YS(1, X))
        If YS(1, X) <= 0 Then
            YS(1, X) = Empty
        End If
    Next X
    
    Dim Q1 As Double
    Dim Q3 As Double
    Dim IQR As Double
    Dim Lower As Double
    Dim Upper As Double
        
    On Error Resume Next
    Q1 = Application.WorksheetFunction.Quartile_Inc(YS, 1)
    Q3 = Application.WorksheetFunction.Quartile_Inc(YS, 3)
    IQR = Q3 - Q1
    Lower = Q1 - (Fence * IQR)
    Upper = Q3 + (Fence * IQR)
    On Error GoTo 0

    If Exclude_xs = vbNullString Then
        For X = 1 To UBound(YS, 2)
            If YS(1, X) <> Empty Then
                If YS(1, X) < Lower Then
                    YS(1, X) = Lower
                ElseIf YS(1, X) > Upper Then
                    YS(1, X) = Upper
                End If
            End If
        Next X
    Else
        On Error Resume Next
        Dim Match As Long
        For Y = 1 To UBound(XS, 2)
            Match = InStr(1, Exclude_xs, Left(XS(1, Y), 2), vbTextCompare)
            If Match = 0 Then
                X = Y
                If YS(1, X) <> Empty Then
                    If YS(1, X) < Lower Then
                        YS(1, X) = Lower
                    ElseIf YS(1, X) > Upper Then
                        YS(1, X) = Upper
                    End If
                End If
            End If
        Next Y
        On Error GoTo 0
    End If
    
    QuartileOutlierCorrection = YS
    
End Function

Function information is added to the Macro Table in the 'ThisWorkbook' Sheet giving you intellisense about the Named Arguments in the 'fx' (Formula Box) in Excel. Copy the Code below into the 'ThisWorkbook' Sheet Code Module:

 
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
Private Sub Workbook_Open()
  
    On Error Resume Next
    Dim FunctionName As String
    Dim FunctionDesc As String
    Dim ArgDesc(1 To 4) As String
 
    FunctionName = "QuartileOutlierCorrection"
    FunctionDesc = "Performs quartile outlier correction on a Range of values >=0 with optional exclude time series periods and fence"
    ArgDesc(1) = "Provide the Known_ys as the input values for the algorithm"
    ArgDesc(2) = "Provide the Known_xs as a time series of values for the algorithm"
    ArgDesc(3) = "Optional: A delimited list of Exclude_xs values in any order to exclude from the algorithm"
    ArgDesc(4) = "Optional: A Fence value to adjust the limits of the upper and lower quartiles"
    Application.MacroOptions Macro:=FunctionName, Description:=FunctionDesc, Category:=vbNullString, ArgumentDescriptions:=ArgDesc
    On Error GoTo 0
 
End Sub
 
 
Private Sub Workbook_Open()
 
    On Error Resume Next
    Dim FunctionName As String
    Dim FunctionDesc As String
    Dim ArgDesc(1 To 4) As String

    FunctionName = "QuartileOutlierCorrection"
    FunctionDesc = "Performs quartile outlier correction on a Range of values >=0 with optional exclude time series periods and fence"
    ArgDesc(1) = "Provide the Known_ys as the input values for the algorithm"
    ArgDesc(2) = "Provide the Known_xs as a time series of values for the algorithm"
    ArgDesc(3) = "Optional: A delimited list of Exclude_xs values in any order to exclude from the algorithm"
    ArgDesc(4) = "Optional: A Fence value to adjust the limits of the upper and lower quartiles"
    Application.MacroOptions Macro:=FunctionName, Description:=FunctionDesc, Category:=vbNullString, ArgumentDescriptions:=ArgDesc
    On Error GoTo 0

End Sub

Use the UDF like this in any Worksheet in Excel for a range of any size:

 
1
2
3
4
5
' standard UDF call (Known_ys := values, Known_xs := time periods)
=QuartileOutlierCorrection($B8:$BA8,$B$6:$BA$6)
 
' exclude time periods ($BB$2 is a single cell reference with a comma-delimited list i.e. '3, 21')
=QuartileOutlierCorrection($B8:$BA8,$B$6:$BA$6,$BB$2)
 
 
' standard UDF call (Known_ys := values, Known_xs := time periods)
=QuartileOutlierCorrection($B8:$BA8,$B$6:$BA$6)

' exclude time periods ($BB$2 is a single cell reference with a comma-delimited list i.e. '3, 21')
=QuartileOutlierCorrection($B8:$BA8,$B$6:$BA$6,$BB$2)

Chart demonstrating the VBA UDF Outlier Correction Function on a range of 15 values with a FENCE of 1.5 and excluding the seasonal point 12