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
从动态意义上的术语(未知的行数和未知的列数)获取每个有效行的最佳方法是什么?
如果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)
如果空单元格不被视为零且不应跳过:
=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 列中的缺失值将抵消结果
有趣的事实 !!我们可以交换avg
到max
或min
:
将其从 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
是一种重级公式,能够对数组/矩阵执行加法、减法、乘法、除法甚至运行总计......但是,数据集越大=公式计算速度越慢(因为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)
将以上所有内容放在一起,使其具有无限动态性,并且仍然仅限于有效数据集:
=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)
再次,不包括范围内为零的单元格:
前面的公式的对立面是运行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)
对于固定范围C2:G9
,MMULT
平均值为:
=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)
=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)