谷歌表格中无限真实动态范围的平均数组公式

pla*_*er0 0 average google-sheets array-formulas google-query-language google-sheets-formula

例如:

     A       B      C     D     E     F     G     ?
  |======|=======|=====|=====|=====|=====|=====|=====
1 |      |AVERAGE|     |     |     |     |     |        
  |======|=======|=====|=====|=====|=====|=====|=====
2 | xx 1 |       |   1 |   2 | 0.5 |  10 |     |        
  |======|=======|=====|=====|=====|=====|=====|=====
3 | xx 2 |       |   7 |   1 |     |     |     |       
  |======|=======|=====|=====|=====|=====|=====|=====
4 |      |       |   0 |     |     |     |     |       
  |======|=======|=====|=====|=====|=====|=====|=====
5 | xx 3 |       |   9 |   8 |   7 |   6 |     |       
  |======|=======|=====|=====|=====|=====|=====|=====
6 | xx 4 |       |   0 |   1 |   2 |   1 |     |       
  |======|=======|=====|=====|=====|=====|=====|=====
7 |      |       |   1 |     |   4 |     |     |       
  |======|=======|=====|=====|=====|=====|=====|=====
8 | xx 5 |       |     |     |     |     |     |       
  |======|=======|=====|=====|=====|=====|=====|=====
9 |      |       |     |     |     |     |   5 |           
  |======|=======|=====|=====|=====|=====|=====|=====
? |      |       |     |     |     |     |     |       
Run Code Online (Sandbox Code Playgroud)

AVERAGE从动态意义上的术语(未知的行数未知的列数)获取每个有效行的最佳方法是什么?

pla*_*er0 5

询问

1级:

如果C2:G范围内的所有 5 个单元格都有值:

=QUERY(QUERY(C2:G, "select (C+D+E+F+G)/5"), "offset 1", )
Run Code Online (Sandbox Code Playgroud)

在此处输入图片说明

如果不是,则跳过行:

在此处输入图片说明

如果空单元格被视为零:

=INDEX(QUERY(QUERY({C2:G*1}, "select (Col1+Col2+Col3+Col4+Col5)/5"), "offset 1", ))
Run Code Online (Sandbox Code Playgroud)

在此处输入图片说明

要删除零值,我们使用IFERROR(1/(1/...))包装:

=INDEX(IFERROR(1/(1/QUERY(QUERY({C2:G*1}, 
 "select (Col1+Col2+Col3+Col4+Col5)/5"), "offset 1", ))))
Run Code Online (Sandbox Code Playgroud)

在此处输入图片说明

为了使Col引用动态化,我们可以这样做:

=INDEX(IFERROR(1/(1/QUERY(QUERY({C2:G*1}, 
 "select "&
 "("&JOIN("+", "Col"&ROW(INDIRECT("1:"&COLUMNS(C:G))))&")/"&COLUMNS(C:G)), 
 "offset 1", ))))
Run Code Online (Sandbox Code Playgroud)

在此处输入图片说明


第 2 级:

如果空单元格不被视为零且不应跳过:

=INDEX(TRANSPOSE(QUERY(TRANSPOSE(E2:I), 
 "select "&TEXTJOIN(",", 1, IF(A2:A="",,
 "avg(Col"&ROW(A2:A)-ROW(A2)+1&")")))),, 2)
Run Code Online (Sandbox Code Playgroud)

在此处输入图片说明

请注意,这是 A 列相关,因此 A 列中的缺失值将抵消结果

有趣的事实 !!我们可以交换avgmaxmin

在此处输入图片说明

将其从 A 列的限制中释放出来并使其适用于任何有效行:

=INDEX(IFERROR(1/(1/TRANSPOSE(QUERY(TRANSPOSE(
 IF(TRIM(TRANSPOSE(QUERY(TRANSPOSE(C2:G),,9^9)))="", C2:G*0, C2:G)), 
 "select "&TEXTJOIN(",", 1, 
 "avg(Col"&ROW(A2:A)-ROW(A2)+1&")"))))),, 2)
Run Code Online (Sandbox Code Playgroud)

在此处输入图片说明

如果范围内的 0 不应该被平均,我们可以添加一个小的 IF 语句:

=INDEX(IFERROR(1/(1/TRANSPOSE(QUERY(TRANSPOSE(
 IF(TRIM(TRANSPOSE(QUERY(TRANSPOSE(
 IF(C2:G>0, C2:G, )),,9^9)))="", C2:G*0, 
 IF(C2:G>0, C2:G, ))), 
 "select "&TEXTJOIN(",", 1, 
 "avg(Col"&ROW(A2:A)-ROW(A2)+1&")"))))),, 2)
Run Code Online (Sandbox Code Playgroud)

在此处输入图片说明

在这里,我们使用了所谓的“垂直查询粉碎”,它获取给定范围内的所有值并将其集中到一个列中,其中每行的所有单元格都与作为副产品的空白连接起来:

=FLATTEN(QUERY(TRANSPOSE(C2:G),,9^9))
Run Code Online (Sandbox Code Playgroud)

在此处输入图片说明

除此之外,还有“水平查询粉碎”

=QUERY(C2:G,,9^9)
Run Code Online (Sandbox Code Playgroud)

在此处输入图片说明

以及“终极 360° 双查询粉碎”,它将范围内的所有单元格放入一个单元格中:

=QUERY(FLATTEN(QUERY(TRANSPOSE(C2:G),,9^9)),,9^9)
Run Code Online (Sandbox Code Playgroud)

在此处输入图片说明

最后是“臭名昭著的负 360° 反向双重查询粉碎”,它优先考虑列而不是行:

=QUERY(FLATTEN(QUERY(C2:G,,9^9)),,9^9)
Run Code Online (Sandbox Code Playgroud)

在此处输入图片说明

当然,所有查询 smash 名称均受版权保护

回到主题......如上所述,范围内每行的所有单元格都与空白空间相连,即使是那些空白的空间,所以我们遇到了在值之间获得双倍或多个空格的情况。为了解决这个问题,我们使用TRIM并引入了一个简单的IF语句来为给定范围内的空行分配 0 值,例如。抵消偏移量:

在此处输入图片说明


MMULT

第 3 级:

MMULT是一种重级公式,能够对数组/矩阵执行加法、减法、乘法、除法甚至运行总计..​​....但是,数据集越大=公式计算速度越慢(因为MMULT即使是空行也需要时间来执行+ - × ÷操作) ...除非我们在两个方向上都使用真正的无限动态范围...

获取具有给定范围值的最后一行:

=INDEX(MAX(IF(TRIM(FLATTEN(QUERY(TRANSPOSE(
 INDIRECT("C2:"&ROWS(A:A))),,9^9)))="",,ROW(A2:A))))
Run Code Online (Sandbox Code Playgroud)

在此处输入图片说明

获取具有给定范围值的最后一列:

=INDEX(MAX(IF(TRIM(QUERY(INDIRECT("C2:"&ROWS(A:A)),,9^9))="",,COLUMN(C2:2))))
Run Code Online (Sandbox Code Playgroud)

在此处输入图片说明

现在我们可以用一种简单的方式构造它:

=INDIRECT("C2:"&ADDRESS(9, 7))
Run Code Online (Sandbox Code Playgroud)

这与:

=INDEX(INDIRECT("C2:"&ADDRESS(MAX(IF(TRIM(FLATTEN(QUERY(TRANSPOSE(
 INDIRECT("C2:"&ROWS(A:A))),,9^9)))="",,ROW(A2:A))), 
 MAX(IF(TRIM(QUERY(INDIRECT("C2:"&ROWS(A:A)),,9^9))="",,COLUMN(C2:2))))))
Run Code Online (Sandbox Code Playgroud)

在此处输入图片说明

或更短的替代方案:

=INDEX(INDIRECT("C2:"&ADDRESS(
 MAX((INDIRECT("C2:"&ROWS(A:A))<>"")*ROW(A2:A)), 
 MAX((INDIRECT("C2:"&ROWS(A:A))<>"")*COLUMN(C2:2)))))
Run Code Online (Sandbox Code Playgroud)

在此处输入图片说明

因此简化的 MMULT 公式将是:

=ARRAYFORMULA(IFERROR(
 MMULT(N(   C2:G9),           ROW(INDIRECT("C1:C"&COLUMNS(C:G)))^0)/
 MMULT(N(IF(C2:G9<>"", 1, )), ROW(INDIRECT("C1:C"&COLUMNS(C:G)))^0)))
Run Code Online (Sandbox Code Playgroud)

在此处输入图片说明

如果我们想从范围中排除零值,则公式为:

=ARRAYFORMULA(IFERROR(
 MMULT(N(   C2:G9),         ROW(INDIRECT("C1:C"&COLUMNS(C:G)))^0)/
 MMULT(N(IF(C2:G9>0, 1, )), ROW(INDIRECT("C1:C"&COLUMNS(C:G)))^0)))
Run Code Online (Sandbox Code Playgroud)

在此处输入图片说明

第 4 级:

将以上所有内容放在一起,使其具有无限动态性,并且仍然仅限于有效数据集:

=INDEX(IFERROR(
 MMULT(N(   INDIRECT("C2:"&ADDRESS(
 MAX((INDIRECT("C2:"&ROWS(A:A))<>"")*ROW(A2:A)), 
 MAX((INDIRECT("C2:"&ROWS(A:A))<>"")*COLUMN(C2:2))))),           ROW(INDIRECT("C1:C"&
 MAX((INDIRECT("C2:"&ROWS(A:A))<>"")*COLUMN(C2:2))-(COLUMN(C2)-1)))^0)/
 MMULT(N(IF(INDIRECT("C2:"&ADDRESS(
 MAX((INDIRECT("C2:"&ROWS(A:A))<>"")*ROW(A2:A)), 
 MAX((INDIRECT("C2:"&ROWS(A:A))<>"")*COLUMN(C2:2))))<>"", 1, )), ROW(INDIRECT("C1:C"&
 MAX((INDIRECT("C2:"&ROWS(A:A))<>"")*COLUMN(C2:2))-(COLUMN(C2)-1)))^0)))
Run Code Online (Sandbox Code Playgroud)

在此处输入图片说明

再次,不包括范围内为零的单元格:

在此处输入图片说明


荣誉奖:

@Erik Tyler级别:

前面的公式的对立面是运行MMULT

  • 总面积代替C2:? (all rows, all columns)
  • 避免大量计算的有效区域C2:? (excluding empty rows and columns)0 × 0 = 0

包括零:

=INDEX(IFERROR(
 MMULT(   INDIRECT("C2:"&ROWS(C:C))*1,         SEQUENCE(COLUMNS(C2:2))^0)/ 
 MMULT(IF(INDIRECT("C2:"&ROWS(C:C))<>"", 1)*1, SEQUENCE(COLUMNS(C2:2))^0)))
Run Code Online (Sandbox Code Playgroud)

在此处输入图片说明

不包括零:

=INDEX(IFERROR(
 MMULT(   INDIRECT("C2:"&ROWS(C:C))*1,       SEQUENCE(COLUMNS(C2:2))^0)/ 
 MMULT(IF(INDIRECT("C2:"&ROWS(C:C))>0, 1)*1, SEQUENCE(COLUMNS(C2:2))^0)))
Run Code Online (Sandbox Code Playgroud)

0

@kishkin级别:

对于固定范围C2:G9MMULT平均值为:

=INDEX(IFERROR(
 MMULT( C2:G9*1,    FLATTEN(COLUMN(C:G))^0)/ 
 MMULT((C2:G9>0)*1, FLATTEN(COLUMN(C:G))^0)))
Run Code Online (Sandbox Code Playgroud)

在此处输入图片说明

=INDEX(IFNA(VLOOKUP(ROW(C2:C), 
 QUERY(SPLIT(FLATTEN(ROW(C2:C)&"×"&C2:J), "×"),
 "select Col1,avg(Col2)
  where Col2 is not null
  group by Col1"), 2, )))
Run Code Online (Sandbox Code Playgroud)

在此处输入图片说明

@MattKing级别:

=INDEX(QUERY(SPLIT(FLATTEN(ROW(C2:C)&"×"&OFFSET(C2,,,9^9, 9^9)), "×"),
 "select avg(Col2) 
  group by Col1  
  label avg(Col2)''"))
Run Code Online (Sandbox Code Playgroud)

在此处输入图片说明

不包括零:

=INDEX(QUERY(SPLIT(FLATTEN(ROW(C2:C)&"×"&OFFSET(C2,,,9^9, 9^9)), "×"),
 "select avg(Col2)
  where Col2 <> 0 
  group by Col1  
  label avg(Col2)''"))
Run Code Online (Sandbox Code Playgroud)

包括空单元格:

=INDEX(IFERROR(1/(1/QUERY(SPLIT(FLATTEN(ROW(C2:C)&"×"&OFFSET(C2,,,9^9, 9^9)*1), "×"),
 "select avg(Col2)
  group by Col1  
  label avg(Col2)''"))))
Run Code Online (Sandbox Code Playgroud)