计算表中动态(溢出)数组元素的出现次数

Counting occurrences of dynamic (spilled) array elements in a table

提问人:PythonNewbie23 提问时间:10/31/2023 最后编辑:Mayukh BhattacharyaPythonNewbie23 更新时间:10/31/2023 访问量:94

问:

我正在使用新的动态结果函数,如 unique、filter、sort、A6# 等。我喜欢它们的大小适合他们返回的物品数量。

我在 Excel 表格中有一个大型数据集(数百列和数千行)。我已使用 unique/filter 函数将满足条件的一列的唯一值提取到动态数组中,没有问题。

现在,我想以动态方式计算每个返回值的出现次数,以便返回值的范围与唯一函数动态返回的唯一值的数量成比例。我可以在过滤函数周围使用计数函数一次计算一个值,但结果不是动态的,需要我手动将函数复制/删除到正确数量的单元格中。

总之,我正在寻找一种方法来计算表列中满足条件且等于动态数组中所有值的项目。结果维度应与动态数组的维度一致。

我从表格中的一些示例数据开始:

颜色 类型 成本 标准
1 1
2 2
1 3
黄色 1 2
1 3
2 1
2 2
黄色 1 3
2 2
1 1
1 3
2 2
黄色 2 1
2 3
2 1

(颜色类型成本标准 红色 1 1 TRUE 蓝色 2 2 FALSE 红色 1 3 TRUE 黄色 1 2 TRUE 橙色 1 3 FALSE 红色 2 1 TRUE 橙色 2 2 错误 黄色 1 3 TRUE 橙色 2 2 错误 蓝色 1 1 TRUE 红色 1 3 TRUE 蓝色 2 2 FALSE 黄色 2 1 TRUE 红色 2 3 错误 红色 2 1 错误)

所需的输出是一个包含两列的区域,即条件为真的唯一颜色,以及出现该颜色且条件为真的出现次数。

生成第一列很简单:

=UNIQUE(FILTER(Table1[Color],Table1[Criteria]))

在此示例中,该函数返回一个三行单列: 红 黄色 蓝 使用返回单个单元格的公式计算该范围中单个成员的出现次数很简单:

=COUNT(FILTER(Table1[Cost],Table1[Criteria]*(Table1[Color]=H10))) 

我使用了 Cost,因为它是数字并且与 Count 配合得更好,而 H10 是“Red”上方动态数组中的单元格之一。

这个函数准确地计算了我想要的东西,但它不会随着返回到上表的颜色数量的变化而缩小和扩展,所以我必须进入并将公式删除/复制到适当的范围。由于我的用户会不断更改条件列,因此通常会留下不同长度的两列。

接下来,我将此公式转换为LET版本,该版本给出了相同的结果。

=LET(lookup,H10,in,Table1[Color],cnt,Table1[Cost],crit,Table1[Criteria],
COUNT(FILTER(cnt,crit*(lookup=in))))

然后,我将公式 (H10) 中对颜色的引用替换为包含它的动态数组 (H10#),结果是值为 0 的单个单元格。

然后我删除了计数函数,只留下过滤器函数,它返回了 NA。因此,filter 函数不处理 H10# 引用,并返回单个值 NA。

我决定我需要编写一个可以处理动态引用的计数函数,我最终得到了:

Public Function DynamicCount(SearchIn, LookFor As Variant As Variant
Dim arr As Variant
Dim idx As Long

    ReDim arr(1 To LookFor.Rows.Count, 1 To 1)
        
    For idx = LBound(arr, 1) To UBound(arr, 1)
        arr(idx, 1) = Application.WorksheetFunction.CountIf(SearchIn, LookFor(idx, 1))
    Next idx
    
    DynamicCount = arr
    
End Function

我首先在没有标准的情况下测试了这一点,只需输入:

=DynamicCount(Table1[Color],H10#)

这有效,从单个单元格返回以下溢出:

6 3 3

然后,我尝试使用以下方法应用标准:

=DynamicCount(FILTER(Table1[Color],Table1[Criteria]),H10#)

这返回了一个值错误!我不确定这是怎么回事。我只评估了过滤器部分:

=FILTER(Table1[Color],Table1[Criteria])

这按预期返回了 8 种颜色的溢出列表。 在稍微玩了一下 vba 代码之后,我认为问题是过滤器函数正在将范围转换为变体数组。不知道如何与他们合作。做了一些 msgbox 调试,当 SearchIn 参数是 Variant(而不是范围)时,它似乎在下一行崩溃。

arr(idx, 1) = Application.WorksheetFunction.CountIf(SearchIn, LookFor(idx, 1))

任何帮助将不胜感激,无论是访问变体数组还是解决问题的其他方法。一定有更简单的方法...... 谢谢

数组 excel vba 动态 用户定义函数

评论


答:

0赞 Ike 10/31/2023 #1

尝试这样 - 不需要 VBA:BYROW

=LET(uniqueColors,UNIQUE(FILTER(table1[Color],table1[Criteria])),
     cntByColor,BYROW(uniqueColors,LAMBDA(r,SUMPRODUCT((table1[Color]=r)*(table1[Criteria])))),
     HSTACK(uniqueColors,cntByColor))

enter image description here

评论

0赞 PythonNewbie23 10/31/2023
谢谢@Ike,这很有帮助。我知道一定有更好的方法,我以前从未使用过 BYROW。我最终得到: =LET( FilteredColors,FILTER(Table1[Color],Table1[Criteria]), UniqueColors,UNIQUE(FilteredColors), NColors,BYROW(UniqueColors,LAMBDA(r,SUM((FilteredColors=r)^2))), HSTACK(UniqueColors,NColors))
0赞 PythonNewbie23 10/31/2023
我将 SUMPRODUCT 更改为 SUM,并试图通过定义 FilteredColors 来避免 SUMPRODUCT 中的数组乘法,但我必须在 SUM 内进行乘法才能使其正常工作,所以我只是平方测试向量。知道为什么在SUM中需要乘法吗?
0赞 Mayukh Bhattacharya 10/31/2023 #2

尝试使用 -- 不需要,也不需要任何辅助功能!!MMULT()VBALAMBDA()

enter image description here


• 细胞中使用的配方F2

=LET(
     α, FILTER(HSTACK(Table_1[Color],Table_1[Criteria]),Table_1[Criteria]),
     Ψ, TAKE(α,,1),
     φ, DROP(α,,1),
     UNIQUE(HSTACK(Ψ,MMULT(N(Ψ=TOROW(Ψ)),φ))))

或者,更短一点的方法:

enter image description here


• 细胞中使用的配方F2

=LET(
     α, HSTACK(Table_1[Color],MMULT(N(Table_1[Color]=TOROW(Table_1[Color])),Table_1[Criteria])),
     UNIQUE(FILTER(α, DROP(α,,1))))

评论

0赞 PythonNewbie23 11/1/2023
这在我的系统上不起作用,它给了 #VALUE!错误(即使我将表名更改为 Table1 之后)。我认为问题在于 MMULT 参数的第二个数组中缺少从布尔到整数的转换。在玩这个时,我在 N 函数中发现了一些意想不到的行为。基本上,如果我按照你的方式传递数组,它会按预期返回一个数组,如果我向它传递一个值,它会按预期返回一个值,但是当我向它传递一个向量时,它会返回一个值。(我试图在 MMULT 调用中使用 N(Table1[Criteria]) 作为参数 2。
0赞 Mayukh Bhattacharya 11/1/2023
嗨,@PythonNewbie23你能给我看一张截图
0赞 PythonNewbie23 11/1/2023
所以,在我了解 N 是怎么回事之前,我决定不使用它。因此,要从布尔值转换为整数,我只需将向量或数组乘以单个值 1。这似乎有效,尽管我不确定它在 N 上是否同样有效。所以我最终得到了这个函数: =LET( α, HSTACK(Table1[Color],MMULT((Table1[Color]=TOROW(Table1[Color]))*1,(Table1[Criteria]*1))), UNIQUE(FILTER(α, DROP(α,,1)))) 这似乎有效。感谢 Bhattacharya @Mayukh帮助
0赞 Mayukh Bhattacharya 11/1/2023
@PythonNewbie23绝对正确的。您还可以使用 or * 或 so 函数在给定值时返回一个数字。N 函数可用于将 TRUE 和 FALSE 分别转换为 1 和 0。当给定文本值时,N 函数返回零+01/1--N()
1赞 PythonNewbie23 11/1/2023
是的,问题似乎在于标准是逻辑值,而不是整数。感谢您的帮助!