【问题标题】:Excel: #CALC! error (Nested Array) when using MAP functions for counting interval overlapsExcel:#计算!使用 MAP 函数计算间隔重叠时出现错误(嵌套数组)
【发布时间】:2022-11-07 22:59:40
【问题描述】:

我正在努力使用以下公式,它适用于某些场景,但不适用于所有场景。名称 input 的数据集失败,出现 #CALC! 错误,描述为“嵌套数组”:

=LET(input, {"N1",0,0;"N1",0,10;"N1",10,20},
  names, INDEX(input,,1), namesUx, UNIQUE(names), dates, FILTER(input, {0,1,1}),
  byRowResult, BYROW(namesUx, LAMBDA(name,
    LET(set, FILTER(dates, names=name),
      startDates, INDEX(set,,1), endDates, INDEX(set,,2), onePeriod, IF(ROWS(startDates)=1, TRUE, FALSE),
      IF(onePeriod, IF(startDates <= IF(endDates > 0, endDates, startDates + 1),0, 1),
        LET(seq, SEQUENCE(ROWS(startDates)),
          mapResult, MAP(startDates, endDates, seq, LAMBDA(start,end,idx,
            LET(incIdx, 1-N(ISNUMBER(XMATCH(seq,idx))),
              startInc, FILTER(startDates, incIdx), endInc, FILTER(endDates, incIdx),
              MAP(startInc, endInc,LAMBDA(ss,ee, N(AND(start <= ee, end >= ss))))
              ))),
              SUM(mapResult)))
    ))), HSTACK(namesUx, byRowResult)
)

如果我们将前面公式中的 input 值替换为以下范围:A2:C4,在 G1:H1 中将是预期产出

还提供了一个图形表示来可视化间隔及其相应的重叠。从屏幕截图中,我们有2 重叠。

如果我们对相同的范围使用上面的公式,我们会得到以下输出:

如果我们将鼠标悬停在 #CALC! 单元格上,它会告知具体错误:

让我们解释一下输入数据和公式的作用:

输入数据

  • 第一列:N1、N2、N3,代表名称
  • 第二列:间隔的开始(我使用的是数值,但在我的实际情况下是日期)
  • 第三列:间隔结束(我使用的是数值,但在我的实际情况下是日期)

公式

该公式的目的是识别每个唯一的names,有多少间隔重叠。计算按唯一名称的每一行 (BYROW) 进行,并且对于每对起始结束值,计算相对于其他起始结束值的重叠。我使用FILTER 排除当前的起始端对,条件如下:FILTER(startDates, incIdx) 并且我测试它工作正常。

排除BYROW的当前迭代名称的起始数据的条件如下:

1-N(ISNUMBER(XMATCH(seq,idx)))

并用作FILTER 函数的第二个输入参数。

剩下的只是检查overlap range condition

name 只有一个间隔时,我将逻辑与其他间隔分开,因为计算不同,对于单个间隔,我只想检查结束日期是否在开始日期之后并处理0 的特殊情况。我测试过的这个特殊情况是有效的。

测试和解决方法

我已经隔离了在哪里是问题和什么时候它发生了。问题发生在以下调用中:

MAP(startInc, endInc,LAMBDA(ss,ee, N(AND(start <= ee, end >= ss))))

startIncendInc 有不止一行时。它与LAMBDA 函数的内容无关。我可以用:

MAP(startInc, endInc,LAMBDA(ss,ee, 1))

仍然失败。问题在于输入数组:startIncendInc。如果我使用任何其他数组,例如以下数组,它就不起作用:

MAP(seq,LAMBDA(ss, 1))

使用namesstartDates 等的类似结果,即使我使用:{1;2;3} 失败。如果使用 use idx 它可以工作,因为它不是一个数组。因此,任何类型的数组或范围都会发生错误。

我还测试了输入参数是否正确,具有正确的形状和值。例如,将MAP 函数替换为:TEXTJOIN(",",, startInc)&amp;" ; "(以及endInc)并将SUM 替换为CONCAT 以连接结果。

在输入数据方面,我测试了以下场景:

{"N1",0,0;"N1",0,10} -> Works
{"N1",0,0;"N1",0,10;"N2",10,0;"N2",10,20;"N3",20,10} -> Works
{"N1",0,0;"N1",0,10;"N1",10,20} -> Error
{"N1",0,0;"N1",0,10;"N1",10,0} -> Error
{"N1",0,0;"N1",0,10;"N1",10,0;"N1",20,10} -> Error
{"N1",0,0;"N1",0,10;"N2",10,0;"N2",10,20;"N2",20,10} -> Error

有效的情况是因为它转到MAP 函数一个大小为1 的数组(重复名称的数量小于3

我在互联网上对#CALC! 错误进行了一些研究,但没有关于此错误的太多详细信息,并且仅提供了一个非常微不足道的案例。我在新数组函数的嵌套调用限制中没有发现任何迹象:BYROWMAP 等。

结论,似乎以下嵌套结构会产生此错误:

=MAP({1;2;3}, LAMBDA(n, MAP({4;5;6}, LAMBDA(s, TRUE))))

即使是这样的微不足道的情况。

相反,以下情况有效:

=MAP({1;2;3}, LAMBDA(n, REDUCE("",{4;5;6}, LAMBDA(a,s, TRUE))))

因为REDUCE 的输出不是数组。

关于如何在我的原始公式中规避这个限制的任何建议?,这是一个不能使用另一个数组作为输入的数组的真实情况吗?,这是一个错误吗?

【问题讨论】:

  • 不确定我是否理解。这只是设计使LAMBDA's计算参数应返回单个值而不是数组。至于替代解决方案,有一些具有预期输出的示例输入可能会更有帮助;修改您当前的公式可能比从头开始解决问题更耗时。
  • 谢谢@JosWoolley,你说得很好。我找到了一种方法来规避删除第二个MAP 的错误。我提供了一个包含更多细节的答案,但我没有接受它,以防其他人可以提供更好的答案。如果有帮助,请在问题中添加示例输入/输出。

标签: arrays excel excel-formula excel-lambda


【解决方案1】:

正如@JosWoolley 指出的那样:

LAMBDA 的计算参数应该返回单个值而不是 大批

我没见过,或者从#CALC! Nested Array error definition推导出来的:

尝试输入数组公式时发生嵌套数组错误 包含一个数组。要解决该错误,请尝试删除第二个 数组...例如,=MUNIT({1,2}) 要求 Excel 返回 1x1 数组和 2x2 数组,目前不支持。 =MUNIT(2) 将按预期计算

所以替代方法是删除第二个MAP 调用。以下链接让我知道了如何做到这一点:Identify overlapping dates and times in Excel,因此使用SUMPRODUCTSUM 可以达到目的。

=LET(input, {"N1",0,0;"N1",0,10;"N1",10,20},
  names, INDEX(input,,1), namesUx, UNIQUE(names), dates, FILTER(input, {0,1,1}),
  byRowResult, BYROW(namesUx, LAMBDA(name,
    LET(set, FILTER(dates, names=name),
      startDates, INDEX(set,,1), endDates, INDEX(set,,2), 
      onePeriod, IF(ROWS(startDates)=1, TRUE, FALSE),
      IF(onePeriod, IF(startDates <= IF(endDates > 0, endDates, startDates + 1),0, 1),
        LET(seq, SEQUENCE(ROWS(startDates)),
          mapResult, MAP(startDates, endDates, seq, LAMBDA(start,end,idx,
            LET(incIdx, 1-N(ISNUMBER(XMATCH(seq,idx))),
              startInc, FILTER(startDates, incIdx), endInc, FILTER(endDates, incIdx),
              SUMPRODUCT((startInc <= end) * (endInc >= start ))
              ))),SUM(mapResult)))/2
    ))), HSTACK(namesUx, byRowResult)
)

我们需要将结果除以2,因为我们正在计算两个方向的重叠。 AB 重叠,反之亦然。

它可以进一步简化,因为不需要构建名称:startIncendInc 以排除我们正在检查重叠的范围本身。我们可以包括它并减去一个重叠。这是这样做的方法:

=LET(input, {"N1",0,0;"N1",0,10;"N1",10,20},
  names, INDEX(input,,1), namesUx, UNIQUE(names), dates, FILTER(input, {0,1,1}),
  byRowResult, BYROW(namesUx, LAMBDA(name,
    LET(set, FILTER(dates, names=name),
      startDates, INDEX(set,,1), endDates, INDEX(set,,2), 
      onePeriod, IF(ROWS(startDates)=1, TRUE, FALSE),
      IF(onePeriod, IF(startDates <= IF(endDates > 0, 
        endDates, startDates + 1),0, 1),
        SUM(MAP(startDates, endDates, LAMBDA(start,end,
          SUMPRODUCT((startDates <= end) * (endDates >= start ))-1)))/2)
    ))), HSTACK(namesUx, byRowResult)
)

这里是输出,删除数组作为输入并使用相应的范围A2:C4。还提供间隔的图形表示(突出显示)并在单元格G2 中放置相应的先前公式:

笔记: 由于我们使用SUMPRODUCT 与单个输入,它可以替换为SUM

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-07-23
    • 2017-10-14
    • 1970-01-01
    • 2019-04-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多