Google Sheets ArrayFormula - 前行的平均值
Posted
技术标签:
【中文标题】Google Sheets ArrayFormula - 前行的平均值【英文标题】:Google Sheets ArrayFormula - Avarage values of predecessor rows 【发布时间】:2021-07-25 15:32:42 【问题描述】:我有一个关于再次使用 ArrayFormula 的问题。 我有 2 列(日期时间和货币)的列表。我需要找到最后 50 行的货币列的平均值。我不能在每一行中都使用公式,因为数组的长度可能会有所不同。
我已经尝试过查询(知道它不适用于 ArrayFormula):
=ArrayFormula(query(U2:V; "select AVG(V) where (U > date '"&TEXT(WORKDAY($U139:U;-50); "YYYY-MM-DD")&"' AND U < date '"&TEXT($U139:U; "YYYY-MM-DD")&"') label AVG(V) ''"))
我的下一步是用间接寻址来欺骗它,但这也不起作用:
=ArrayFormula(IF($U2:$U>=$C$32;AVERAGE(INDIRECT("$V"&ROW()):INDIRECT("$V"&ROW()-50));""))
这是一个包含两个公式的示例表:Avarage 50 example
任何想法如何解决这个问题?
【问题讨论】:
AVERAGEIFS()
呢?
这适用于 1 行。我需要在每行中为 50 个前行行提供此信息,而无需复制公式...
对于超过 2500 行以上没有一个好的方法。如果你有兴趣,我可以告诉你这么多的答案,但如果你有比这更长的时间序列,你可能不感兴趣?
虽然我的解决方案没有列出所有 50 对范围的优雅,但它将作为单个单元格 ARRAYFORMULA
工作。如果开始日期是 24/06/1998 17:30:00,它将平均滚动 50 天,处理 5790 行数据。
【参考方案1】:
既然你说“我需要找到最后 50 行的货币列的平均值”,你可以使用这个:
=ArrayFormula(query(D2:E; "select AVG(Col2) where (Col1 > date '"&TEXT(WORKDAY($D139:D;-50); "YYYY-MM-DD")&"' AND Col1 < date '"&TEXT($D139:D; "YYYY-MM-DD")&"') label AVG(Col2) ''"))
但是你说“我需要在每一行中为 50 行前行而不复制公式”,所以这是我能想到的将公式放在一个单元格中的最佳方法:
=query(C2:C;"where Col1 is null limit 49";0);query(ARRAYFORMULA(if(E2:E="";"";(E2:E+E3:E+E4:E+E5:E+E6:E+E7:E+E8:E+E9:E+E10:E+E11:E+E12:E+E13:E+E14:E+E15:E+E16:E+E17:E+E18:E+E19:E+E20:E+E21:E+E22:E+E23:E+E24:E+E25:E+E26:E+E27:E+E28:E+E29:E+E30:E+E31:E+E32:E+E33:E+E34:E+E35:E+E36:E+E37:E+E38:E+E39:E+E40:E+E41:E+E42:E+E43:E+E44:E+E45:E+E46:E+E47:E+E48:E+E49:E+E50:E+E51:E)/50));"limit "&counta(E2:E)-49&" ";0)
注意:公式必须在第 2 行!在其他任何地方,它可能会导致您的工作表添加更多行时出现问题。
要使query(C2:C;"where Col1 is null limit 49";0)
正常工作并偏移数组公式,您必须至少有 49 个空白单元格。如果不是,请参考其他列。
由于您的样本表位于德国,因此我不得不使用 ;而不是 , 作为函数分隔符。
更新
如果您创建一个名为“RowsToAverage”的命名范围,其中包含您想要平均的行数(即 50),这里是一个修改后的公式:
=query(C2:C;"where Col1 is null limit "&RowsToAverage-1&"";0);query(ARRAYFORMULA(if(E2:E="";"";(E2:E+E3:E+E4:E+E5:E+E6:E+E7:E+E8:E+E9:E+E10:E+E11:E+E12:E+E13:E+E14:E+E15:E+E16:E+E17:E+E18:E+E19:E+E20:E+E21:E+E22:E+E23:E+E24:E+E25:E+E26:E+E27:E+E28:E+E29:E+E30:E+E31:E+E32:E+E33:E+E34:E+E35:E+E36:E+E37:E+E38:E+E39:E+E40:E+E41:E+E42:E+E43:E+E44:E+E45:E+E46:E+E47:E+E48:E+E49:E+E50:E+E51:E)/RowsToAverage));"limit "&counta(E2:E)-(RowsToAverage-1)&" ";0)
您仍然需要手动创建范围(E2:E+E3:E+E4:E+E5:E+E6:E+E7:E+E8:E+E9:E+E10:E+E11:E+E12:E+E13:E+E14:E+E15:E+E16:E+E17:E+E18:E+E19:E+E20:E+E21:E+E22:E+E23:E+E24:E+E25:E+E26:E+E27:E+E28:E+E29:E+E30:E+E31:E+E32:E+E33:E+E34:E+E35:E+E36:E+E37:E+E38:E+E39:E+E40:E+E41:E+E42:E+E43:E+E44:E+E45:E+E46:E+E47:E+E48:E+E49:E+E50:E+E51:E)
,但他可以在另一个单元格中轻松完成,然后复制到上面的公式中:
=textjoin("+";true;arrayformula("E"&row(indirect("A2:A"&RowsToAverage+1))&":E"))
【讨论】:
很好!我在我的电子表格中做了一些工作,因为 50 有时也不是一个固定数字。但我设法接近到足以让它发挥作用!这是一个非常粗糙和不优雅的尝试,但它确实有效。谢谢。 :) 如果您想快速生成范围,请使用以下命令,其中 RowsToAverage 是您的号码的命名范围(或号码本身,无论您喜欢哪个):=textjoin("+";true;arrayformula("E"&row(indirect("A2:A"&RowsToAverage+1))&":E"))
【参考方案2】:
MMULT() 可用于创建这样的条件平均值或求和,但它们仅限于 2500 行以下的数据集,因为它们实际上会创建一个 N 行长、N 列宽的矩阵,其中N 是数据集的长度。
N^2 必须小于 500 万,因为这是 google 表格中的“单元格限制”。
您会在名为 MK.Help 的新选项卡上的单元格 F2 中找到此公式:
=ARRAYFORMULA(IF((E2:E="")+(ROW(D2:D)<50+1);;MMULT((ROW(D2:D)<=TRANSPOSE(ROW(D2:D)+50))*(ROW(D2:D)>=TRANSPOSE(ROW(D2:D)));N(E2:E))/50))
【讨论】:
哇,我很欣赏这种方法。尽管如此,我认为它可能是 非常精致和优雅的方法。不幸的是你是对的:当我把它移到我原来的电子表格中时,我总是会遇到限制错误。但是谢谢你... :) 使用脚本(每天触发)来记录资产(股票、硬币等)的收盘价对于所有试图跟踪和分析资产的工作表来说是一种非常简单的方法。 @Me.MyBase以上是关于Google Sheets ArrayFormula - 前行的平均值的主要内容,如果未能解决你的问题,请参考以下文章
使用 Sheets API v4 Java 阅读整个 Google 电子表格
使用 Sheets API v4 (Java) 获取 Google 表格上次编辑日期
请求时Google Sheets HttpError 403