我有一个相当大的数据集,我需要将多个条目组合成一个值。我的数据集包含两个数据集组合的数据,每个数据集都使用自己的ID和密钥。
我想过使用像这样的Sumproduct()
函数:
=SUMPRODUCT(--('Raw data'!C:C=Landgebruik!A2);--('Raw data'!O:O={20;21;22;23;40});'Raw data'!S:S)
Landgebruik!A2
持有第一个数据集的ID,我需要将第二个数据集聚合到。
'Raw data'!O:O
包含第二个数据集中的ID。在上面的例子中,当第二个ID的值是这些值中的任何一个时,我需要对面积(在'Raw data'!S:S
中)求和:{20;21;22;23;40}
。 (OR逻辑)该列仅包含整数值。
有没有其他方法来解决这个问题,然后为数组中的所有值复制--('Raw data'!O:O=20)
?
编辑:
我现在就去处理,那是:=SUMPRODUCT(--('Raw data'!C:C=Landgebruik!A2);--('Raw data'!O:O=20)+('Raw data'!O:O=20)+('Raw data'!O:O=21)+('Raw data'!O:O=22)+('Raw data'!O:O=23)+('Raw data'!O:O=40);'Raw data'!S:S)
。但我觉得应该有更优雅的方式来做这件事。
您可以使用文本搜索:
--NOT(ISERROR(FIND('Raw data'!O:O,"2021222340")))
但是你必须要小心,在更长的ID中找不到更短的ID,例如如果你想在ID {123,456,789}中搜索,那么12不被认为是ID。所以像上面这样简单的文本搜索是行不通的。您需要一个分隔符来分解ID字符串。通常我会为此目的使用管道字符,因为我不记得它出现在Excel文件的原始文本中的任何情况,并且因为它使公式成为人类可读的:
--NOT(ISERROR(FIND("|"&'Raw data'!O:O&"|","|20|21|22|23|40|")))
例子:
'原始数据'!O:O是20 => | 21 |发现于| 20 | 21 | 22 | 23 | 40 |
'原始数据'!O:O是2 => | 2 |在| 20 | 21 | 22 | 23 | 40 |中找不到
(如果你的ID可能包含管道字符,那么你可以使用CHR(1),一个长期遗忘的SOH的ASCII代码意味着标题的开头;当然,它的可读性较差。)
整个公式:
=SUMPRODUCT(--('Raw data'!C:C=Landgebruik!A2),--NOT(ISERROR(FIND("|"&'Raw data'!O:O&"|","|20|21|22|23|40|"))),'Raw data'!S:S)
(抱歉,我的Excel使用,而不是;)
尽管之前已经完成了数百次,但是他们可能会将微软公司的公式或其他东西改为开源。
我偏爱Jerry和Me建议的方法,因为它们很简单,简洁,但你付出了沉重的性能成本。
汤姆的公式看起来很难看,但到目前为止速度最快,比我最初的例子快4倍。我们能够将{} s与Tom的公式结合起来,但是要使它工作,我们必须用sum函数包装sumifs函数。这大大减慢了配方,但使它更漂亮。
z32a7ul也有一个很好的解决方案。我非常喜欢使用 - 并学会了如何使用| s来搜索文本而只搜索该文本。乍一看,我认为它不适用于像2323这样的数字,但确实如此。
模拟示例如下:
A1:A5000充满了LandgeBruik,
B1:B5000充满了40年代
C1:5000充满了1。
结果:
=SUMPRODUCT((A1:A5000="LandgeBruik")*(B1:B5000={20,21,22,23,40})*C1:C5000)
经过了19.186031秒| 59,818,073个蜱虫
{=SUM(IF(A1:A5000="Landgebruik",1,0)*IF(B1:B5000={20,21,22,23,40},1,0)*C1:C5000)}
经过了26.124411秒| 81,450,506个蜱虫
{=SUM((A1:A5000=""Landgebruik"")*(B1:B5000={20,21,22,23,40})*C1:C5000)}
经过了21.111835秒| 65,822,330个蜱虫
"=SUMIFS(C1:C5000,B1:B5000,"">=20"",B1:B5000,""<=23"",A1:A5000,""=Landgebruik"")+SUMIFS(C1:C5000,B1:B5000,""=40"",A1:A5000,""=Landgebruik"")"
6.732804秒过去了| 20,991,490个蜱虫
"=SUM(SUMIFS(C1:C5000,A1:A5000,"Landgebruik",B1:B5000,{21,22,23,24,40}))"
经过了16.954528秒| 52,860,709个蜱虫
"=SUMPRODUCT(--(A1:A5000=""Landgebruik""),--NOT(ISERROR(FIND(""|""&B1:B5000&""|"",""|20|21|22|23|40|""))),C1:C5000)"
经过了11.822379秒| 36,859,729个蜱虫
您可以将其拆分为两个SUMIFS,如注释中所述。如果所有值都是整数,则比较'原始数据'!O:O到20,21,22和23与测试> = 20和<= 23相同。值40必须单独完成。
=SUMIFS('Raw Data'!S:S,'Raw Data'!C:C,Landgebruik!A2,'Raw Data'!O:O,">="&20,'Raw Data'!O:O,"<="&23)
+SUMIFS('Raw Data'!S:S,'Raw Data'!C:C,Landgebruik!A2,'Raw Data'!O:O,40)
在我的语言环境中
要么
=SUMIFS('Raw Data'!S:S;'Raw Data'!C:C;Landgebruik!A2;'Raw Data'!O:O;">="&20;'Raw Data'!O:O;"<="&23)
+SUMIFS('Raw Data'!S:S;'Raw Data'!C:C;Landgebruik!A2;'Raw Data'!O:O;40)
在您的语言环境中。
仅当几个条件是连续整数时才有效。
速度考虑
SUMIFS被认为比sumproduct快约五倍,因此可能是大型数据集的首选选项as demonstrated here
您可以争辩说,来自@ BrakNicku的SUM中(有效)五个SUMIFS的更一般的建议应该和一个SUMPRODUCT一样快,但SUM(SUMIFS)可能仍然会赢,因为像SUMIFS这样的公式可以更有效地处理全列引用比数组公式。
在向OP提出一些澄清之后,我想对这个问题给出一个解释,因为英语不是我的主要语言而且我认为我误解了一些东西。
那么,我做了什么来模拟情况,制作了一张2张新工作簿。
一张名为Landgebruik
,并在A2
得到一个值,我这样做:
第二张名为Raw data
。我隐藏了一些列以仅使用列C,O和S.在列SI输入中,只有值等于1.在列OI中,随机值等于{20,21,22,23,40}
,而在列CI中,随机值为A或B.它看起来像这(请注意我隐藏了一些列):
并且问题想要在列S中加总值,但仅限于列O等于20或21或22或23 o 40且列C等于Landgebruik!A2
(在我的测试中,值中有字母A
)
我们可以使用数组公式来过滤S列中的数据,然后在过滤后,将总和值满足要求。在我的测试中,正确的结果将是8,因为S列中只有8个值符合C和O列的要求。在图像中,右侧行以黄色突出显示。
OP已经做到了这一点,但想知道是否有更短/更优雅的配方。
我找到的最短公式是这样的:
=SUM(IF($O$2:$O$28={20;21;22;23;40};IF($C$2:$C$28=Landgebruik!$A$2;$S$2:$S$28)))
这是一个数组公式,所以必须按CTRL + SHIFT + ENTER插入它,否则它将无法工作!
这个怎么运作:
第一个IF
获取列S中的所有值,并忽略列O中等效的所有值不是20或21或22或23或40的所有值。第二个IF
获取该新数组,并忽略列C中的等价物不等于Landgebruik!$A$2
的所有值。最终数组由函数SUM
提供
我试着尽力解释。我希望你能适应你的需求。
如果您对性能(计算速度)感兴趣并且不怕矩阵计算,可以使用MMULT:
=SUMPRODUCT(--('Raw data'!C:C=Landgebruik!A2),MMULT(--('Raw data'!O:O={20,21,22,23,24}),TRANSPOSE({1,1,1,1,1})),'Raw data'!S:S)
说明:
首先,创建一个1048576×5矩阵,如果“原始数据”中的ID,则第i行和第j列的值为1!O:O的第i行与第j行相同枚举值{20,21,22,23,24},否则为0。
其次,将此乘以1的向量(5 1,因为{20,21,22,23,24}包含五个元素),这意味着您接受所有五个值。
第三,从上面你得到一个向量,其中如果ID在可接受的值中,则第i个元素为1,否则为0,并且将此向量放在SUMPRODUCT中的其他元素旁边。
(抱歉,我的Excel使用','而不是';'。如果你想缩短公式,你可以写{1; 1; 1; 1; 1}而不是TRANSPOSE({1,1,1,1, 1})。但你必须找出你的Excel使用而不是';'来分隔行,很可能是'。'。)
注意:如果您参考实际包含值的范围,而不是整列,例如,它可能会提高计算速度。 '原始数据'!C1:C123而不是'原始数据'!C:C。
如果使用Shift + Space Ctrl ++在已包含的最后一行上方插入新行,则公式中的引用将自动更新。或者,您可以使用具有特殊公式的名称,通过确定最后一个非空单元格来增大引用的范围。
更新
我做了一些测量来比较这些方法的效率。我使用10000行的随机数据,我重新计算每个公式1000次。您可以在第二列中查看已用时间。
当我运行这个VBA代码来测量时间时,我注释掉了其他公式:
Public Sub MeasureCalculationTime()
Dim datStart As Date: datStart = Now
Dim i As Long: For i = 1 To 1000
Application.Calculate
Next i
Dim datFinish As Date: datFinish = Now
Dim dblSeconds As Double: dblSeconds = (datFinish - datStart) * 24 * 60 * 60
Debug.Print "Calculation finished at " & datFinish; " took " & dblSeconds & " seconds"
End Sub
在这种情况下,MMULT不是最快的。
但是,我想指出它是最灵活的因为
注意:上面的行只是伪代码,MMULT只有两个参数。
这可能有效:
={SUMPRODUCT(--('Raw data'!C:C=Landgebruik!A2);--IFERROR(MATCH('Raw data'!O:O;{20;21;22;23;40};0)>0;0);'Raw data'!S:S)}
这需要作为数组公式输入。