在Excel中评估数组中的INDIRECT
我想写一个线性回归函数,dynamic引用列,可以处理#N/A
值,并将随着时间的推移添加额外的行。 这是一个示例数据集:
Date Value 1 Value 2 1/2/1991 #N/A #N/A 2/4/2002 276.36 346.31 1/7/2003 252 350 1/21/2004 232 345.5 1/6/2005 257 368 2/1/2006 278.24 390.11 2/23/2007 #N/A 380.46 2/11/2008 326.34 383.04 2/12/2009 #N/A 399.9 2/17/2009 334.39 #N/A 1/29/2010 344.24 400.83 1/27/2011 342.88 404.52 2/7/2012 379 417.91 1/23/2013 #N/A 433.35
这是我迄今为止所开发的基于这个论坛post的function 。 它计算值1的线性回归。
=TRANSPOSE( LINEST( N( OFFSET( INDIRECT("B2" & ":B" & COUNTA(B:B)), SMALL( IF( ISNUMBER( INDIRECT("A2:A" & COUNTA($A:$A)) * INDIRECT("B2" & ":B" & COUNTA(B:B))), ROW(INDIRECT("B2:B" & COUNTA(B:B))) - ROW(B2)), ROW(INDIRECT("1:" & MIN( COUNT(INDIRECT("A2:A" & COUNTA($A:$A))), COUNT(INDIRECT("B2:B" & COUNTA(B:B))))))), 0, 1)), N( OFFSET( INDIRECT("A2:A" & COUNTA($A:$A)), SMALL( IF( ISNUMBER( INDIRECT("A2:A" & COUNTA($A:$A)) * INDIRECT("B2:B" & COUNTA(B:B))), ROW(INDIRECT("B2:B" & COUNTA(B:B))) - ROW(B2)), ROW(INDIRECT("1:" & MIN( COUNT(INDIRECT("A2:A" & COUNTA($A:$A))), COUNT(INDIRECT("B2:B" & COUNTA(B:B))))))), 0, 1)), TRUE, FALSE))
按照目前编写的方式,将我的数组拖到右侧以解决Value 2需要手动更新公式。 INDIRECT
公式中的所有引号必须手动从B
更改为C
我有40列的数据,所以我试图使公式完全dynamic使用ADDRESS
, ROW
和COLUMN
:
=TRANSPOSE( LINEST( N( OFFSET( INDIRECT(ADDRESS(2, COLUMN(B2)) & ":" & ADDRESS(COUNTA(B:B), COLUMN(B2))), SMALL( IF( ISNUMBER( INDIRECT("A2:A" & COUNTA($A:$A)) * INDIRECT(ADDRESS(2, COLUMN(B2)) & ":" & ADDRESS(COUNTA(B:B), COLUMN(B2)))), ROW(INDIRECT(ADDRESS(2, COLUMN(B2)) & ":" & ADDRESS(COUNTA(B:B), COLUMN(B2)))) - ROW(B2)), ROW(INDIRECT("1:" & MIN( COUNT(INDIRECT("A2:A" & COUNTA($A:$A))), COUNT(INDIRECT(ADDRESS(2, COLUMN(B2)) & ":" & ADDRESS(COUNTA(B:B), COLUMN(B2)))))))), 0, 1)), N( OFFSET( INDIRECT("A2:A" & COUNTA($A:$A)), SMALL( IF( ISNUMBER( INDIRECT("A2:A" & COUNTA($A:$A)) * INDIRECT(ADDRESS(2, COLUMN(B2)) & ":" & ADDRESS(COUNTA(B:B), COLUMN(B2)))), ROW(INDIRECT(ADDRESS(2, COLUMN(B2)) & ":" & ADDRESS(COUNTA(B:B), COLUMN(B2)))) - ROW(B2)), ROW(INDIRECT("1:" & MIN( COUNT(INDIRECT("A2:A" & COUNTA($A:$A))), COUNT(INDIRECT(ADDRESS(2, COLUMN(B2)) & ":" & ADDRESS(COUNTA(B:B), COLUMN(B2)))))))), 0, 1)), TRUE, FALSE))
这给了我#REF!
。 当我对公式进行一步一步的评估时,Excel评估COLUMN
时,问题就出现了。 它在公式中引入了大括号,通过其余的INDIRECT
评估传播。 这是一个快速的比较:
原始配方:
INDIRECT("B2:B15")
dynamic公式:
INDIRECT({"$B$2:$B$15"})
评估结果为#VALUE
,此时公式的其余部分被打破。 有没有办法强制Excel在这个评估中不使用大括号,还是有更好的方法来做这个计算?
你只是试图从线性回归中获得SLOPE
吗? 如果是这样,可以在将SLOPE
#N/A
转换为空格(在公式中使用IFERROR
)之后使用SLOPE
函数。 然后SLOPE
只是抛出空白。 如果您还想要拦截,请使用以下相同的公式,并将INTERCEPT
replace为SLOPE
。
范围的图片
公式是数组公式(使用CTRL + SHIFT + ENTER)并复制。 鉴于这种安排,简单的公式(非dyanmic)将是:
=SLOPE(IFERROR(B2:B15,""),$A$2:$A$15)
如果你想要这些是dynamic的,你可以使用INDEX
和COUNTA
来获得dynamic范围。
=SLOPE(IFERROR(B2:INDEX(B:B,COUNTA(B:B)),""),$A$2:INDEX($A:$A,COUNTA($A:$A)))
用一个Table
来代替
更好的是,你可以在一个Table
定义这个数据,然后使用这个头文件来获取整个列。 该公式看起来不错,复制容易。
仍然在这里使用数组公式,但唯一的variables是用于查看Table1
的列标题。 这个数据将会对上面使用的COUNTA
的数据更加抵制。
=SLOPE(IFERROR(INDEX(Table1,,MATCH(M1,Table1[#Headers])),""),Table1[Date])
看来你可以使用下面的,更短,非易失性的数组公式** :
=LINEST(INDEX(B:B,N(IF(1,MODE.MULT(IF(ISNUMBER(B2:B15),{1,1}*ROW(B2:B15)))))),INDEX($A:$A,N(IF(1,MODE.MULT(IF(ISNUMBER(B2:B15),{1,1}*ROW(B2:B15)))))))
B2:如果需要,可以根据Jeeped解决schemedynamic定义B15。
问候
您将尽可能地摆脱使用INDIRECT函数 ; 当然,因为它涉及用列参考replacestring等价物。 看来很多可以用INDEX / MATCH函数对的forms来replace。
=TRANSPOSE( LINEST( N( OFFSET(B2:INDEX(B:B, MATCH(1E+99,$A:$A )), SMALL( IF( ISNUMBER( $A2:INDEX($A:$A, MATCH(1E+99,$A:$A )) * B2:INDEX(B:B, MATCH(1E+99,$A:$A ))), ROW(B2:INDEX(B:B, MATCH(1E+99,$A:$A ))) - ROW(B2)), ROW(INDIRECT("1:" & MIN( COUNT($A2:INDEX($A:$A, MATCH(1E+99,$A:$A ))), COUNT(B2:INDEX(B:B, MATCH(1E+99,$A:$A ))))))), 0, 1)), N( OFFSET( $A2:INDEX($A:$A, MATCH(1E+99,$A:$A )), SMALL( IF( ISNUMBER( $A2:INDEX($A:$A, MATCH(1E+99,$A:$A )) * B2:INDEX(B:B, MATCH(1E+99,$A:$A ))), ROW(B2:INDEX(B:B, MATCH(1E+99,$A:$A ))) - ROW(B2)), ROW(INDIRECT("1:" & MIN( COUNT($A2:INDEX($A:$A, MATCH(1E+99,$A:$A ))), COUNT(B2:INDEX(B:B, MATCH(1E+99,$A:$A ))))))), 0, 1)), TRUE, FALSE))
根据需要向右填充并locking列A,而列B的单元格区域引用将转移到列C,D等。
进一步的functionreplace可能会交换至less一些OFFSETfunction用于适当的INDEXfunction,但公式似乎现在正常工作。