8

我有一个相当大的数据集,我需要将多个条目组合成一个值。我的数据集包含两个数据集组合的数据,每个数据集都使用自己的 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,我需要将第二个数据集聚合到该 ID 。

'Raw data'!O:O包含来自第二个数据集的 ID。在上述情况下,'Raw data'!S:S当第二个 ID 的值是以下任何值时,我需要对面积 (in ) 求和:{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). 但我觉得应该有一种更优雅的方式来做到这一点。

4

7 回答 7

6

即使这已经完成了数百次,嘿,也许微软改变了公式或其他东西。

我偏爱 Jerry 和 Me 建议的方法,因为它们非常简单和简洁,但是您付出了沉重的性能成本。

Tom 的公式在我看来很难看,但迄今为止最快,比我最初的例子快 4 倍。我们能够将 {} 与 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 滴答

于 2019-02-18T07:18:42.283 回答
6

您可以为此使用文本搜索:

--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 使用 , 而不是 ;)

于 2019-02-21T13:53:18.697 回答
5

如评论中所述,您可以将其拆分为两个 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 快大约五倍,因此可能是大型数据集的首选选项,如此处所示

您可能会争辩说,@ BrakNicku 的 SUM 中(有效)五个 SUMIFS 的更一般建议应该与一个 SUMPRODUCT 一样快,但是 SUM(SUMIFS) 可能仍然会获胜,因为像 SUMIFS 这样的公式可以更有效地处理全列引用比数组公式。

于 2019-02-16T10:51:48.557 回答
5

你可以对你当前的公式做一个小的改变;更改;*--在该特定情况下也不需要):

=SUMPRODUCT(('Raw data'!C:C=Landgebruik!A2)*('Raw data'!O:O={20;21;22;23;40})*'Raw data'!S:S)

这应该有效。


当您向 提供单独的参数时SUMPRODUCT,每个参数必须具有相同的大小。但是当你像这样将它们相乘时,它会强制评估并且数组会扩展。

例如,如果你取两个数组,5x1 和 1x5,你会得到一个 5x5 的结果数组:

在此处输入图像描述

于 2019-02-19T06:27:23.273 回答
4

在要求 OP 进行一些澄清之后,我想试一试这个问题,因为英语不是我的主要语言,我认为我误解了一些东西。

所以,我做了什么来模拟情况,用两张纸制作了一个新的工作簿。

一张纸被命名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

我已经尽力解释了。我希望你能适应你的需要。

于 2019-02-19T14:42:03.090 回答
4

如果对性能(计算速度)感兴趣,又不怕矩阵计算,可以使用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 矩阵,如果 'Raw data' 中的 ID 与第 j 行相同,则第 i 行第 j 列的值为 1!O:O 的第 i 行枚举 {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 并不是最快的。

但是,我想指出它是最灵活的,因为

  1. 您可以将它与开关一起使用:您引用单元格范围而不是 {1,1,1,1,1},您将能够非常快速地在选择中包含/排除 ID。就像您放入 A1:A5 {20,21,22,23,24} 并在它旁边放入 B1:B5 {1,1,1,1,1}。如果要排除 21,则将 B2 重写为 0,如果要包含,则将其写回 1。

  2. 您可以使用更复杂的标准,您必须在其中比较多个级别。像:

    =SUMPRODUCT(MMULT(--(CarId=CarOwner),--(CarOwner=ListOfJobs),--(ListOfJobs=JobsByDepartment),--(DepartmentIncludedInSelection=1)),FuelConsumption)

注意:上面这行只是伪代码,MMULT只有两个参数。

于 2019-02-21T14:21:31.523 回答
-1

这可以工作:

={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)}

这需要作为数组公式输入。

于 2019-02-15T13:41:04.197 回答