我们可以使用嵌套的 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
的每一行上使用 MAX
或 QUERY
。原因是公式“消耗”了整个范围。这使它变得更加困难。这样做的方法是首先生成一个包含所有值的 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)
。这可以通过 ARRAYFORMULA
和 SEQUENCE
:
一起实现
=
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)&") ''")
)
)
)
参考资料
我尝试使用 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
的每一行上使用 MAX
或 QUERY
。原因是公式“消耗”了整个范围。这使它变得更加困难。这样做的方法是首先生成一个包含所有值的 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)
。这可以通过 ARRAYFORMULA
和 SEQUENCE
:
=
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)&") ''")
)
)
)