找到零之前的非零数字的平均值?

Find average of non-zero numbers preceding a zero?

我有一列数字,我想计算零前面所有非零数字的平均值。例如:如果我有一个名为 Units 的列,我希望在编写公式时填充 Average 列。

Units Average
32     32 
33     32
31     32
 0      0
 0      0
 1      2
 2      2
 3      2
 0      0
 1      1.5
 2      1.5

excel 中是否有使用公式执行此操作的方法?

虽然没有我希望的那么简单和简短,但是,这里是:

Option Base 1
Function myavg(r As Range)
  Dim i%, i0%, j%, n%, ia, a, oa()
  ia = r
  n = UBound(ia, 1)     ' get number of rows
  ReDim oa(n, 1)        ' prepare an output array with same no of rows
  a = 0:  i0 = 0        ' a:  accumulator summing up values
                        ' i0: position of last 0 value found
  For i = 1 To n        ' go through all input rows
    If (ia(i, 1) = 0) Then ' current value is zero:
      oa(i, 1) = 0         ' set output value to 0
     If i > i0 + 1 Then
      a = a / (i - i0 - 1)    ' calculate average value of previous group
      For j = i0 + 1 To i - 1 ' and assign it to output array
        oa(j, 1) = a
      Next j
      a = 0                ' reset the accumulator
     End If
     i0 = i
    Else
     a = a + ia(i, 1)      ' add to accumulator
    End If
  Next i

  If i > i0 + 1 Then       ' do average calculation for last group
   a = a / (i - i0 - 1)    ' if it was not ended with a 0 value
   For j = i0 + 1 To i - 1
       oa(j, 1) = a
   Next j
  End If

  myavg = oa
End Function

user-defined 工作表函数用作 matrix-function。这意味着您必须 select 目标范围(即 C2:C12)),输入 =myavg(B2:B12) 之类的函数,然后按 <shift><ctrl><return>。这会将函数作为矩阵函数应用。

函数将被大括号 {} 包围,就像

如果您只使用一个辅助列,您可以使用公式非常简单地完成此操作,如下所示[假设您的数据位于从 A2 开始的 A 列中,您的辅助列位于从 B2 开始的 B 列中,并且您的结果将在从 C2 开始的 C 列中]:

辅助栏[放入B2并向下拖动]:

=IF(A2=0, "", IF(A1=0,MAX(B:B1)+1,B1))

这将创建一个唯一标识符,每当 A 列中有一个 non-zero 值时向上迭代 1,并且上面一行中的值为 0。即:一组行将全部具有相同的 ID 号,直到出现带有 0 的行 - 然后下一个数字块的 ID 号将比最后一组高 1。请注意,B2 需要硬编码为 1,否则使 A1 等于 0。

[C2并向下拖动]中的结果列:

=AVERAGEIFS(A:A,B:B,B2)

这会获取 A 列中与辅助列中创建的标识符匹配的所有行的平均值。

只是为了展示一种完全不同的方法:

Public Function special_average(rng As Range)
  If rng.Value = 0 Then special_average = "": Exit Function
  Dim i As Long, lower_rng As Range, str As String
  Set lower_rng = rng

  If rng.Row > 1 Then str = rng.Offset(-1, 0).Text
  While str <> "0" And Len(str) > 0 And IsNumeric(str) And rng.Row > 1
    Set rng = rng.Offset(-1, 0)
    str = rng.Offset(-1, 0).Text
  Wend

  If lower_rng.Row < Rows.Count Then str = lower_rng.Offset(1, 0).Text Else str = ""
  While str <> "0" And Len(str) > 0 And IsNumeric(str) And lower_rng.Row < Rows.Count
    Set lower_rng = lower_rng.Offset(1, 0)
    str = lower_rng.Offset(1, 0).Text
  Wend

  special_average = Application.WorksheetFunction.Average(rng.Parent.Range(rng, lower_rng))
End Function

在这种情况下,您只需输入一个单元格。它会自动上下移动以获得平均范围。所以对于 B5 你只需要 =special_average(A5).

不过,我会使用 等级 'Eh' 培根 的答案。如果禁用宏,它将很快并且也可以工作。

编辑: 要显示公式方式的不同方法(没有辅助列),您可以输入 B2 然后向下复制:

=IF(A2=0,"",IF(ISNUMBER(B1)*(B1<>0),B1,IFERROR(AVERAGE(OFFSET(A2,0,0, MATCH(0,A2:A1000,0)-1)),AVERAGE(A2:A1000))))

缺点是,您需要设置最大范围(本例中为 999 行,必要时可以扩展)