我们可以使用嵌套的 FormulaArray 来计算时间序列中所有间隔的最大值吗?

Can we use nested FormulaArray to compute the maximum for all interval in a time series?

我尝试使用 FormulaArray 计算时间序列内所有固定长度间隔的最大值。例如,假设我们有“日期”的 A 列和“值”的 B 列,我正在尝试类似

ArrayFormula(Max(Filter(B1:B, DAYS(A1:A,A1:A) > t, DAYS(A1:A,A1:A) < 2*t)))

其中 t 是某个常数。这是,对于每一行,我想计算

MAX(FILTER(Bi:B, DAYS(Ai:A,Ai) > t, DAYS(Ai:A, Ai) < 2*t))

我正在寻找使用 ArrayFormula 或替代方案但不使用 Query 的解决方案。

无法在使用 ARRAYFORMULA 的每一行上使用 MAXQUERY。原因是公式“消耗”了整个范围。这使它变得更加困难。这样做的方法是首先生成一个包含所有值的 table,然后使用 QUERY 为每列取最大值。

第 0 步:准备有用的信息

有 2 个值会变得非常方便。第一个是 t。我在 E2 上将其设置为 2,并添加了一个 header。第二个是我们拥有的值的数量。这需要一个公式,将转到 F2:

=MAX(ARRAYFORMULA(if(A:A<>"";row(A:A);0)))-1

公式基本上就是最后一个非空行的数字减1(因为我们跳过了1行,所以headers)。

第 1 步:Table 所有数字

公式为:

=
ARRAYFORMULA(
  IFNA(
    IF(
      A2:A<>"";
      VLOOKUP(
        A2:A+SEQUENCE(1; E2+1; E2);
        A2:B;
        2;
        false
      );
      ""
    );
    -9999
  )
)

您需要将其添加到第 1 行或第 2 行以获得足够的行(它会扩展到最后一行)。

主要技巧是当 t 等于 2 时 SEQUENCE(1; E2+1; E2) 将是 {2; 3; 4}。数组公式将其与 A2:A 结合以生成一个 3 宽的二维数组。看看它是如何展开的:

=
ARRAYFORMULA(
  A2:A+SEQUENCE(1; E2+1; E2)
)

您会注意到它们具有您想从中获取值的日期的值。

然后我们使用 VLOOKUP 将这个“索引”转换为实际值。添加一个 IF 和一个 IFNA 以防止出现问题,你明白了!

步骤 2 删除空行

此步骤以后会更简单,因为您使用的数据较少,我们无论如何都不感兴趣。为此,我们可以简单地添加一个 ARRAY_CONSTRAIN:

=
ARRAY_CONSTRAIN(
  TRANSPOSE(
    <formula on step 1>
  );
  E2+1;
  F2
)

步骤 3.1 将查询添加到组合中

查询操作column-by-column。这意味着我们需要转置值,使用查询进行操作,并转置回原始方向。这看起来像:

=
TRANSPOSE(
  QUERY(
    TRANSPOSE(
      <formula on step 2>
    );
    <query>
  )
)

步骤 3.2 生成查询

现在我们有了正确的值,我们需要生成查询。这是因为列数会增加。

基本查询是:

select MAX(Col1), MAX(Col2), MAX(Col3) label MAX(Col1) '', MAX(Col2) '', MAX(Col3) ''

select部分相当self-explanatory。 lebel 部分用于删除 headers,因此我们只获取值。

要生成我们需要生成的值 MAX(ColN)。这可以通过 ARRAYFORMULASEQUENCE:

一起实现
=
ARRAYFORMULA("MAX(Col"&SEQUENCE(F2)&")"

我们在标签的末尾添加 '',因此它将是:

=
ARRAYFORMULA("MAX(Col"&SEQUENCE(F2)&") ''"

现在我们用逗号连接它们并将整个查询放在一起:

=
"SELECT "&
JOIN(
  ",";
  ARRAYFORMULA("MAX(Col"&SEQUENCE(F2)&")")
)&
" label "&
JOIN(
  ",";
  ARRAYFORMULA("MAX(Col"&SEQUENCE(F2)&") ''")
)

第 4 步:将所有内容放在一起

如果你把所有东西放在一起你会得到:

=
TRANSPOSE(
  QUERY(
    TRANSPOSE(
      ARRAY_CONSTRAIN(
        ARRAYFORMULA(
          IFNA(
            IF(
              A2:A<>"";
              VLOOKUP(
                A2:A+SEQUENCE(1; E2+1; E2);
                A2:B;
                2;
                false
              );
              ""
            );
            -9999
          )
        );
        F2;
        E2+1
      )
    );
    "SELECT "&
    JOIN(
      ",";
      ARRAYFORMULA("MAX(Col"&SEQUENCE(F2)&")")
    )&
    " label "&
    JOIN(
      ",";
      ARRAYFORMULA("MAX(Col"&SEQUENCE(F2)&") ''")
    )
  )
)

参考资料