Calculate Moving Average in Excel

雨燕双飞 提交于 2019-12-19 04:18:52

问题


I want to calculate a moving average of the last, say 20, numbers of a column. A problem is that some of the cells of the column may be empty, they should be ignored. Example:

 A
175
154

188
145
155

167
201

A moving average of the last three would be (155+167+201)/3. I've tried to implement this using average, offset, index, but I simply don't know how. I'm a little bit familiar with macros, so such a solution would work fine: =MovingAverage(A1;3)

Thanks for any tips or solutions!


回答1:


{=SUM(($A$1:A9)*(ROW($A$1:A9)>LARGE((ROW($A$1:A9))*(NOT(ISBLANK($A$1:A9))),3+1)))/3}

Enter this with control+shift+enter to make it an array formula. This will find the latest three values. If you want more or less, change the two instances of '3' in the formula to whatever you want.

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

This part returns the 4th highest row number of all the cells that have a value, or 5 in your example because rows 6, 8, and 9 are the 1st through 3rd highest rows with a value.

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

This part returns 9 TRUEs or FALSEs based on whether the row number is larger than the 4th largest.

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

This multiplies the values in A1:A9 by those 9 TRUEs or FALSEs. TRUEs are converted to 1 and FALSEs to zero. This leaves a SUM function like this

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

Because all the values above 155 don't satisfy the row number criterion, the get multiplied by zero.




回答2:


If you are going to use a UDF it will only recalculate correctly when you change the data if the parameters include all the range of data you want to handle.

Here is a moving average UDF that handles entire columns and contains some error handling.
You can call it using by entering the formula =MovingAverage(A:A,3) into a cell.

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



回答3:


Just a quick solution: Supposing your numbers are on the cells A2:A10, put in B10 the following formula:

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

Dragging up the formula you get the moving average

If there is the possibility of two consecutive blank you could nest another if, more than that and this solution became too complicated




回答4:


I have written a short script in VBA. Hopefull it does what you want. Here you are:

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) I have set limit to 360 cells. It means that the script will not look for more than 360 cells. If you want to change it then change the initial value of counter.

2) The script returns not rounded average. Change the last row to MovingAverage = Round(CDbl(tmp / i),2)

3) The use is just like you wanted, so just type =MovingAverage("a1";3) into the cell.

Any comments are welcome.



来源:https://stackoverflow.com/questions/5283466/calculate-moving-average-in-excel

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!