Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/google-sheets/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Google sheets Google表单中无限真实动态范围上的平均值数组公式_Google Sheets_Google Sheets Formula_Average_Array Formulas_Google Query Language - Fatal编程技术网

Google sheets Google表单中无限真实动态范围上的平均值数组公式

Google sheets Google表单中无限真实动态范围上的平均值数组公式,google-sheets,google-sheets-formula,average,array-formulas,google-query-language,Google Sheets,Google Sheets Formula,Average,Array Formulas,Google Query Language,例如: A B C D E F G ∞ |======|=======|=====|=====|=====|=====|=====|===== 1 | |AVERAGE| | | | | | |======|=======|=====|=====|=====|=====|=====|===== 2 | xx 1 | | 1 | 2

例如:

     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 |           
  |======|=======|=====|=====|=====|=====|=====|=====
∞ |      |       |     |     |     |     |     |       
对于术语的动态意义上的每个有效行(行的未知数量&列的未知数量),获取
平均值的最佳方法是什么?

查询 第一级: 如果范围C2:G中的所有5个单元格都有值:

=QUERY(QUERY(C2:G, "select (C+D+E+F+G)/5"), "offset 1", )

如果不是,则跳过行:

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

如果将空单元格视为零:

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

要删除零值,我们使用
IFERROR(1/(1/…)
wrapping:

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

要使
Col
引用动态,我们可以执行以下操作:

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


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

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

请注意,这是列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)

如果不应平均范围内的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)

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

=FLATTEN(QUERY(TRANSPOSE(C2:G),,9^9))

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

=QUERY(C2:G,,9^9)

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

=QUERY(FLATTEN(QUERY(TRANSPOSE(C2:G),,9^9)),,9^9)

最后,“臭名昭著的负360°反向双查询粉碎”,它将列优先于行:

=QUERY(FLATTEN(QUERY(C2:G,,9^9)),,9^9)

当然,所有查询粉碎名称都受版权保护

回到话题上来。。。如上所述,范围中每行的所有单元格都用空格连接,即使是那些空格,所以我们得到了一种情况,即值之间有两个或多个空格。为了解决这个问题,我们使用
TRIM
,并引入一个简单的
IF
语句,为给定范围内的空行分配0值,例如,计数器偏移:


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

要获取具有给定范围值的最后一行,请执行以下操作:

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

要获取具有给定范围值的最后一列,请执行以下操作:

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

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

=INDIRECT("C2:"&ADDRESS(9, 7))
这与:

=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))))))

或更短的备选方案:

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

第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)))

不包括零:

=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)))
=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)))
=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)''"))

级别: 对于固定范围
C2:G9
而言,
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)))
=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)))
=INDEX(IFERROR(
 MMULT( C2:G9*1,    FLATTEN(COLUMN(C:G))^0)/ 
 MMULT((C2:G9>0)*1, FLATTEN(COLUMN(C:G))^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)))
=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)))
=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)''"))

你花了很多时间。我希望人们能欣赏它,更多的是为了别人,而不是为了你自己

查看最终公式,这些公式应产生相同的结果(在C2中给出数据:?如示例中所示):

在B2中(包括零):

=ArrayFormula(IFERROR(MMULT(间接(“C2:&行(C:C))*1,序列(列(C1:1),1,1,0))/MMULT(IF(间接(“C2:&行(C:C))”),1,0,序列(列(C1:1),1,1,0))

在B2中(不包括零):

=ArrayFormula(IFERROR(MMULT)(间接(“C2:&行(C:C))*1,SEQUENCE(列(C1:1),1,1,0))/MMULT(IF(间接(“C2:&行(C:C))0,1,0),SEQUENCE(列(C1:1),1,1,0))
我将尝试对@player0的答案做一些补充。我真的很感激任何关于优化这个的评论


如果数据范围内有大量空行和空列,则这些行和空列也可以从
MMULT
中排除

步骤1-过滤掉空行 我们得到了一个数据范围:从
C2
到最后一行,再到最后一列(即
J:J
)。我将使用
C2:K
,请参见下面的详细说明

这个公式将为我们提供一个行号数组,其中至少有一个非空单元格。如果有空行,它也将有一个
0
,但在这个数组中搜索并不重要,或者我们会在重要时过滤掉它:

=ARRAYFORMULA(
  UNIQUE(FLATTEN((C2:K <> "") * ROW(C2:K)))
)
步骤2-过滤掉空列 要获得仅包含非空列号的数组,我们可以使用几乎相同的公式:

=ARRAYFORMULA(
  UNIQUE(FLATTEN((C2:K <> "") * SEQUENCE(1, COLUMNS(C2:K), COLUMN(C2))))
)
要过滤掉空行和空列,我们只需使用两个
filter
s:

=ARRAYFORMULA(
  FILTER(
    FILTER(
      C2:K*1,
      MATCH(
        ROW(C2:K),
        UNIQUE(FLATTEN((C2:K <> "") * ROW(C2:K))),
        0
      )
    ),
    MATCH(
      SEQUENCE(1, COLUMNS(C2:K), COLUMN(C2)),
      UNIQUE(FLATTEN((C2:K <> "") * SEQUENCE(1, COLUMNS(C2:K), COLUMN(C2)))),
      0
    )
  )
)

关于原始数据行,这有点不对劲

第4步-填写平均值列 为了使平均值与原始数据行一致,我们可以使用
VLOOKUP
如下:

=ARRAYFORMULA(
  IFNA(VLOOKUP(
    SEQUENCE(MAX((C2:K <> "") * ROW(C2:K)) - 1, 1, ROW(C2)),
    {
      QUERY(UNIQUE(FLATTEN((C2:K <> "") * ROW(C2:K))), "WHERE Col1 <> 0"),
      MMULT(
        ...
      ) /
      MMULT(
        ...
      )
    },
    2,
    0
  ))
)


一些细节
  • 为了简洁起见,
    INDEX
    可以代替
    ARRAYFORMULA
    (感谢@player0,几个月前教过我这一点),但我喜欢
    ARRAYFORMULA
    的明确性
  • 为了清晰起见,我使用
    SEQUENCE
    来构造一列或一行
    1
    s,使其显式。比如说这个,
但是(这只是我的猜测)我认为
序列
的内部实现应该比提升到电源的操作更简单

  • 我使用range
    C2:K
    ,它比表中实际存在的列多一列。它不仅给出了
    C2
    右侧所有列的范围以及从该列向下的所有行,而且在工作表右侧添加另一列时也会更新:。尽管它没有被突出显示。这个
    C2:K
    几乎可以完美实现(如果s上确实存在
    ZZZ
    列,则会出现问题)
    =ARRAYFORMULA(
      IFNA(VLOOKUP(
        SEQUENCE(MAX((C2:K <> "") * ROW(C2:K)) - 1, 1, ROW(C2)),
        {
          QUERY(UNIQUE(FLATTEN((C2:K <> "") * ROW(C2:K))), "WHERE Col1 <> 0"),
          MMULT(
            FILTER(
              FILTER(
                C2:K*1,
                MATCH(
                  ROW(C2:K),
                  UNIQUE(FLATTEN((C2:K <> "") * ROW(C2:K))),
                  0
                )
              ),
              MATCH(
                SEQUENCE(1, COLUMNS(C2:K), COLUMN(C2)),
                UNIQUE(FLATTEN((C2:K <> "") * SEQUENCE(1, COLUMNS(C2:K), COLUMN(C2)))),
                0
              )
            ),
            SEQUENCE(
              ROWS(
                QUERY(
                  UNIQUE(FLATTEN((C2:K <> "") * SEQUENCE(1, COLUMNS(C2:K), COLUMN(C2)))),
                  "WHERE Col1 <> 0"
                )
              ),
              1,
              1,
              0
            )
          ) /
          MMULT(
            FILTER(
              FILTER(
                (C2:K <> "")*1,
                MATCH(
                  ROW(C2:K),
                  UNIQUE(FLATTEN((C2:K <> "") * ROW(C2:K))),
                  0
                )
              ),
              MATCH(
                SEQUENCE(1, COLUMNS(C2:K), COLUMN(C2)),
                UNIQUE(FLATTEN((C2:K <> "") * SEQUENCE(1, COLUMNS(C2:K), COLUMN(C2)))),
                0
              )
            ),
            SEQUENCE(
              ROWS(
                QUERY(
                  UNIQUE(FLATTEN((C2:K <> "") * SEQUENCE(1, COLUMNS(C2:K), COLUMN(C2)))),
                  "WHERE Col1 <> 0"
                )
              ),
              1,
              1,
              0
            )
          )
        },
        2,
        0
      ))
    )
    
    SEQUENCE(
      ROWS(
        QUERY(
          UNIQUE(FLATTEN((C2:K <> "") * SEQUENCE(1, COLUMNS(C2:K), COLUMN(C2)))),
          "WHERE Col1 <> 0"
        )
      ),
      1,
      1,
      0
    )
    
    SIGN(
      QUERY(
        UNIQUE(FLATTEN((C2:K <> "") * SEQUENCE(1, COLUMNS(C2:K), COLUMN(C2)))),
        "WHERE Col1 <> 0"
      )
    )
    
    QUERY(
      UNIQUE(FLATTEN((C2:K <> "") * SEQUENCE(1, COLUMNS(C2:K), COLUMN(C2)))),
      "WHERE Col1 <> 0"
    )^0
    
    INDIRECT("C2:" & ROWS(C:C))
    
    OFFSET(C2,,, ROWS(C2:C), COLUMNS(C2:2))
    
    =ARRAYFORMULA(
      IFNA(
        VLOOKUP(
          ROW(B2:B),
          QUERY(
            {
              FLATTEN(ROW(C2:J) + SEQUENCE(1, COLUMNS(C2:J),,)),
              FLATTEN(C2:J)
            },
            "SELECT Col1, AVG(Col2)
             WHERE Col2 IS NOT NULL
             GROUP BY Col1"
          ),
          2,
          0
        )
      )
    )
    
    =ARRAYFORMULA(
      QUERY(
        {
          FLATTEN(ROW(C2:J) + SEQUENCE(1, COLUMNS(C2:J),,)),
          FLATTEN(IFERROR(1/(1/C2:J)))
        },
        "SELECT AVG(Col2)
         GROUP BY Col1
         LABEL AVG(Col2) ''"
      )
    )
    
    INDIRECT("C2:" & ROWS(C:C))
    
    OFFSET(C2,,, ROWS(C2:C), COLUMNS(C2:2))
    
    =ARRAYFORMULA(QUERY(SPLIT(FLATTEN(ROW(C2:C)&"|"&OFFSET(C2,,,9^9,9^9)),"|"),"select AVG(Col2) group by Col1 label AVG(Col2)''"))