【问题标题】:Calculate Moving Average in Excel在 Excel 中计算移动平均线
【发布时间】:2011-07-14 02:21:24
【问题描述】:

我想计算一列最后一个数字的移动平均值,比如 20 个。一个问题是该列的某些单元格可能是空的,它们应该被忽略。示例:

 A
175
154

188
145
155

167
201

最后三个的移动平均线为 (155+167+201)/3。我尝试使用平均值、偏移量、索引来实现这一点,但我根本不知道如何。我对宏有点熟悉,所以这样的解决方案可以正常工作:=MovingAverage(A1;3)

感谢您提供任何提示或解决方案!

【问题讨论】:

    标签: excel vba worksheet-function array-formulas


    【解决方案1】:

    只是一个快速的解决方案: 假设您的数字在单元格 A2:A10 上,请在 B10 中输入以下公式:

    =IF(COUNT(A8:A10)=3,AVERAGE(A8:A10),IF(COUNT(A7:A10)=3,AVERAGE(A7:A10),"too many blanks"))
    

    拖动公式得到移动平均线

    如果有可能存在两个连续的空白,您可以嵌套另一个,如果不止于此,此解决方案变得过于复杂

    【讨论】:

    • 这可能有点太复杂了,因为有数百个值并且可能有数十个或更多空单元格。还是谢谢!
    【解决方案2】:
    {=SUM(($A$1:A9)*(ROW($A$1:A9)>LARGE((ROW($A$1:A9))*(NOT(ISBLANK($A$1:A9))),3+1)))/3}
    

    使用 control+shift+enter 输入,使其成为数组公式。这将找到最新的三个值。如果您想要更多或更少,请将公式中“3”的两个实例更改为您想要的任何内容。

    LARGE((ROW($A$1:A9))*(NOT(ISBLANK($A$1:A9))),3+1)
    

    这部分返回所有具有值的单元格的第 4 高行号,在您的示例中为 5,因为第 6、8 和 9 行是具有值的第 1 到第 3 行。

    (ROW($A$1:A9)>LARGE((ROW($A$1:A9))*(NOT(ISBLANK($A$1:A9))),3+1))
    

    这部分根据行号是否大于第 4 大返回 9 个 TRUE 或 FALSE。

    ($A$1:A9)*(ROW($A$1:A9)>LARGE((ROW($A$1:A9))*(NOT(ISBLANK($A$1:A9))),3+1))
    

    这会将 A1:A9 中的值乘以这 9 个 TRUE 或 FALSE。 TRUE 转换为 1,FALSE 转换为零。这留下了一个像这样的 SUM 函数

    =SUM({0;0;0;0;0;155;0;167;201})/3
    

    因为155以上的所有值都不满足行号标准,所以get乘以零。

    【讨论】:

    • 聪明的解决方案。我喜欢你对 Row 和 Large 的使用。 +1
    • 我为我正在使用的公式修改了这个答案,但无法进一步找到最后 4 个值中最低 3 个的平均值。我在这里发布了一个问题:stackoverflow.com/questions/22972920/…
    【解决方案3】:

    我用 VBA 编写了一个简短的脚本。希望它做你想要的。你在这里:

    Function MovingAverage(ByVal r As String, ByVal i As Integer) As Double
    Dim rng As Range, counter As Long, j As Integer, tmp As Double
        Set rng = Range(r)
        counter = 360
        j = 0
        tmp = 0
        While j < i + 1 And counter > 0
            If Len(rng.Offset(j, 0)) > 0 Then
                tmp = tmp + rng.Offset(j, 0).Value
            End If
            j = j + 1
            counter = counter - 1
        Wend
        MovingAverage = CDbl(tmp / i)
    End Function
    

    1) 我已将限制设置为 360 个单元格。这意味着该脚本不会查找超过 360 个单元格。如果要更改它,请更改 counter 的初始值。

    2) 脚本返回非四舍五入的平均值。将最后一行更改为 MovingAverage = Round(CDbl(tmp / i),2)

    3) 用途如您所愿,因此只需在单元格中输入 =MovingAverage("a1";3)

    欢迎任何cmets。

    【讨论】:

    • 这个脚本似乎是从上到下计算平均值。我想平均一列的最后 3 个值。不过,我想我可以弄清楚如何。谢谢!
    【解决方案4】:

    如果您要使用 UDF,只有在参数包含您要处理的所有数据范围时,它才会在您更改数据时正确重新计算。

    这是一个处理整个列并包含一些错误处理的移动平均 UDF。
    您可以通过在单元格中输入公式 =MovingAverage(A:A,3) 来调用它。

    Function MovingAverage(theRange As Range, LastN As Long) As Variant
        Dim vArr As Variant
    
        Dim j As Long
        Dim nFound As Long
        Dim dSum As Double
    
        On Error GoTo Fail
        MovingAverage = CVErr(xlErrNA)
        '
        ' handle entire column reference
        '
        vArr = Intersect(Application.Caller.Parent.UsedRange, theRange).Value2
    
        If IsArray(vArr) And LastN > 0 Then
            For j = UBound(vArr) To 1 Step -1
                ' skip empty/uncalculated
                If Not IsEmpty(vArr(j, 1)) Then
                    ' look for valid numbers
                    If IsNumeric(vArr(j, 1)) Then
                        If Len(Trim(CStr(vArr(j, 1)))) > 0 Then
                            nFound = nFound + 1
                            If nFound <= LastN Then
                                dSum = dSum + CDbl(vArr(j, 1))
                            Else
                                Exit For
                            End If
                        End If
                    End If
                End If
            Next j
    
            If nFound >= LastN Then MovingAverage = dSum / LastN
    
        End If
        Exit Function
    Fail:
        MovingAverage = CVErr(xlErrNA)
    End Function
    

    【讨论】:

    • 感谢您提供完整的 UDF!
    猜你喜欢
    • 1970-01-01
    • 2014-11-18
    • 2020-02-04
    • 2012-01-21
    • 2010-09-22
    相关资源
    最近更新 更多