Excel – 计算与ID匹配的唯一值,针对100,000个案例进行优化

在参考下面的excel屏幕截图时,我正在寻找一个公式解决scheme,它可以计算列A中每个ID号的列B(颜色)中唯一值的数量。

我已经在C列中列出了所需的结果。因此,例如,ID 1(A2)只有一个唯一的颜色Gray(B2),它将在C2中返回1。 ID 2只有一个唯一的颜色,即黄色(B3,B4),并在C3和C4中返回1。 ID 3,有两个独特的颜色,蓝色和紫色,从而通过C8在C5中返回一个2。 等等。

因为这将会运行近10万行,我所遇到的很多基于索引和/或匹配的解决scheme都需要很长的时间来计算。 我已经发现ID值,这些都是升序,可以用来加速通过启动公式= IF(A2 = A1,或类似的东西。感谢任何人有一些想法如何用精益的公式解决这个问题。

注意:我使用的文件也接近100列。 不需要帮助栏的解决scheme将是理想的。

编辑/添加:在我的主要数据文件中,在B列中有空白单元格的实例。有没有办法在计算C列结果时忽略空白单元格?

在这里输入图像说明

这是一个VBA例程,应该快速运行这些条目。 我们创build一个类模块(用户定义的对象),它由与每个ID相关的颜色的集合(字典)以及该颜色的计数组成。 (实际上并不需要计数,但是添加它并不重要,以防其他用途,也可以作为一些可以完成的工作的示范)。

然后,我们将结果输出到相邻的列中,如您在屏幕截图中所示。 结果可以在其他地方输出,即使在不同的工作表上,只需稍作修改即可。

请务必阅读模块开头的注意事项,以获取重要信息和正确设置。

类模块


Option Explicit 'RENAME this module: cID Private pID As String Private pColor As String Private pColors As Dictionary Public Property Get ID() As String ID = pID End Property Public Property Let ID(Value As String) pID = Value End Property Public Property Get Color() As String Color = pColor End Property Public Property Let Color(Value As String) pColor = Value End Property Public Property Get Colors() As Dictionary Set Colors = pColors End Property Public Function ADDColor(Value As String) 'Might as well also count # of times this color assigned If Not pColors.Exists(Value) Then pColors.Add Key:=Value, Item:=1 Else pColors(Value) = pColors(Value) + 1 End If End Function Private Sub Class_Initialize() Set pColors = New Dictionary End Sub 

常规模块

编辑编辑,以消除计数的空白行


 Option Explicit 'Set reference to Microsoft Scripting Runtime (Tools/References) Sub IDColorCount() Dim cID As cID, dID As Dictionary Dim wsData As Worksheet, rData As Range Dim vData As Variant, vRes As Variant Dim I As Long 'Set the data worksheet and range 'Read the data into an array for faster calculations Set wsData = Worksheets("sheet1") With wsData Set rData = .Range(.Cells(1, 1), .Cells(.Rows.Count, 1).End(xlUp)).Resize(columnsize:=2) vData = rData End With 'Go through the data and collect the information Set dID = New Dictionary For I = 2 To UBound(vData, 1) If Not vData(I, 1) = "" Then Set cID = New cID With cID .ID = vData(I, 1) .Color = vData(I, 2) .ADDColor .Color If Not dID.Exists(.ID) Then dID.Add Key:=.ID, Item:=cID Else dID(.ID).ADDColor .Color End If End With End If Next I 'Size the results array ReDim vRes(1 To UBound(vData), 1 To 1) vRes(1, 1) = "Count" For I = 2 To UBound(vData, 1) If Not vData(I, 1) = "" Then _ vRes(I, 1) = dID(CStr(vData(I, 1))).Colors.Count Next I 'The results can be written anyplace With rData.Offset(0, 2).Resize(columnsize:=1) .EntireColumn.Clear .Value = vRes End With End Sub 

好的,我使用这个数组公式解决了你的问题:

 =SUM(IF(FREQUENCY(IF($A$2:$A$21=A2,MATCH($B$2:$B$21,$B$2:$B$21,0),""),MATCH($B$2:$B$21,$B$2:$B$21,0))>0,1)) 

将此公式放入单元格C2并按Ctrl + Shift + Enter ,然后将公式向下。 如有任何问题,请在下面留言