表 ArrayFormula。按组查找最近的数字
Sheets ArrayFormula. Find nearest number by group
主数据
组值对
1 | 1
1 | 2
1 | 3
2 | 5
2 | 8
3 | 10
3 | 12
工作数据
组值对 + 期望的结果
1 | 4 | 3 (3≤4, max in group 1)
1 | 2 | 2 (2≤2, max in group 1)
2 | 6 | 5 (5≤6, max in group 2)
3 | 7 | no result (both 10 and 12 > than 7)
任务是从一组中找到最大可能匹配的数字,该数字应小于或等于给定的数字。
对于Group 1, value 4
:
=> filter Master Data (1,2,3) => find 3
做一次就没问题,需要用arrayformula做。
我尝试使用 vlookup
公式的修改来解决它,但到目前为止输出错误。
样本和我的工作“舞台”:
https://docs.google.com/spreadsheets/d/11Cd2BGpGN-0h2bL0LQ_EpIDBKKT2hvTVHoxGC6i8uTE/edit?usp=sharing
注意:不需要用单个公式求解,因为它可能会减慢结果。
我的解决方案基于逐行查找最大数的技术。示例公式在这里:
https://docs.google.com/spreadsheets/d/1VY157ykKsCVDqEKDBp3oAVaG0LTXAz8wUCggCrFXMDM/edit#gid=628408999
我的整个解决方案在这里:
https://docs.google.com/spreadsheets/d/11Cd2BGpGN-0h2bL0LQ_EpIDBKKT2hvTVHoxGC6i8uTE/edit#gid=0
第 1 步
从大师Table.
获取按组加入号码
1 | 3,2,1
2 | 8,5
3 | 12,10
用offset
实现了这个↑。并使用 vlookup
将此 semi-result 与工作 table.
相匹配
第 2 步
使用if
+ split
检查结果值是否≤我的工作值,并在同一公式中使用查询查找每行的最大值。
撰写查询:使用 join
+ sequence
=IF(M3=0,,"select "&JOIN(", ",INDEX("max(Col"&SEQUENCE(M3)&")")))
结果:
select max(Col1), max(Col2), max(Col3), max(Col4), max(Col5)
找到每组的最大值:
=index(TRANSPOSE(QUERY(TRANSPOSE(data), "select ...")))
这个最终公式是解决问题的方法。
注意:结果:我的公式的 0 表示“不匹配”。这对我来说很好。
尝试:
=INDEX(IFNA(IF(E4:E>=
VLOOKUP(D4:D&TEXT(E4:E, "00000"), {A4:A&TEXT(FILTER(B4:B, B4:B<>""), "00000"), B4:B}, 2),
VLOOKUP(D4:D&TEXT(E4:E, "00000"), {A4:A&TEXT(FILTER(B4:B, B4:B<>""), "00000"), B4:B}, 2), 0)))
我用过
=ArrayFormula(VLOOKUP(D4:D8&text(E4:E8,"0000"),A4:A10&text(B4:B10,"0000"),1,true))
从 J4 开始
然后
=ArrayFormula(if(--left(J4:J8)=D4:D8,--right(J4:J8,4),""))
从 K4 开始。
需要进一步细化,但不对前一组的最大值做出任何假设。
编辑
所以在进一步工作之后它看起来像这样
=ArrayFormula(if(D4:D="",,
if(D4:D=
vlookup(D4:D&text(E4:E,"0000"),filter({A4:A&text(B4:B,"0000"),A4:A},A4:A<>""),2,true),
vlookup(D4:D&text(E4:E,"0000"),filter({A4:A&text(B4:B,"0000"),B4:B},A4:A<>""),2,true),"")))
实际上很像@player0 的解决方案。
我想你可以通过做一些像
这样的事情让它更通用一点
=text(B4,rept("0",ceiling(log10(max(B4:B)))))
假设这些都是正整数。
替代方法
我认为这是更好的方法。找出每组的起始行,以及该组中有多少行 r 小于或等于所需的 group/value 对。然后就是从组的第一行往前走r-1行,找到匹配的值:
=ArrayFormula(if(countifs(A4:A,D4:D,B4:B,"<="&E4:E)>0,
vlookup(
vlookup(D4:D,{A4:A,row(A4:A)},2,false)+countifs(A4:A,D4:D,B4:B,"<="&E4:E)-1,{row(A4:A),B4:B},2,false),))
当然假设主数据是按组和值排序的——否则你将不得不使用 sort():
=ArrayFormula(if(countifs(A4:A,D4:D,B4:B,"<="&E4:E)>0,
vlookup(
vlookup(D4:D,{sort(A4:A,A4:A,1,B4:B,1),row(A4:A)},2,false)+countifs(A4:A,D4:D,B4:B,"<="&E4:E)-1,{row(A4:A),SORT(B4:B,A4:A,1,B4:B,1)},2,false),))
主数据
组值对
1 | 1
1 | 2
1 | 3
2 | 5
2 | 8
3 | 10
3 | 12
工作数据
组值对 + 期望的结果
1 | 4 | 3 (3≤4, max in group 1)
1 | 2 | 2 (2≤2, max in group 1)
2 | 6 | 5 (5≤6, max in group 2)
3 | 7 | no result (both 10 and 12 > than 7)
任务是从一组中找到最大可能匹配的数字,该数字应小于或等于给定的数字。
对于Group 1, value 4
:
=> filter Master Data (1,2,3) => find 3
做一次就没问题,需要用arrayformula做。
我尝试使用 vlookup
公式的修改来解决它,但到目前为止输出错误。
样本和我的工作“舞台”:
https://docs.google.com/spreadsheets/d/11Cd2BGpGN-0h2bL0LQ_EpIDBKKT2hvTVHoxGC6i8uTE/edit?usp=sharing
注意:不需要用单个公式求解,因为它可能会减慢结果。
我的解决方案基于逐行查找最大数的技术。示例公式在这里: https://docs.google.com/spreadsheets/d/1VY157ykKsCVDqEKDBp3oAVaG0LTXAz8wUCggCrFXMDM/edit#gid=628408999
我的整个解决方案在这里:
https://docs.google.com/spreadsheets/d/11Cd2BGpGN-0h2bL0LQ_EpIDBKKT2hvTVHoxGC6i8uTE/edit#gid=0
第 1 步
从大师Table.
获取按组加入号码1 | 3,2,1
2 | 8,5
3 | 12,10
用offset
实现了这个↑。并使用 vlookup
将此 semi-result 与工作 table.
第 2 步
使用if
+ split
检查结果值是否≤我的工作值,并在同一公式中使用查询查找每行的最大值。
撰写查询:使用 join
+ sequence
=IF(M3=0,,"select "&JOIN(", ",INDEX("max(Col"&SEQUENCE(M3)&")")))
结果:
select max(Col1), max(Col2), max(Col3), max(Col4), max(Col5)
找到每组的最大值:
=index(TRANSPOSE(QUERY(TRANSPOSE(data), "select ...")))
这个最终公式是解决问题的方法。
注意:结果:我的公式的 0 表示“不匹配”。这对我来说很好。
尝试:
=INDEX(IFNA(IF(E4:E>=
VLOOKUP(D4:D&TEXT(E4:E, "00000"), {A4:A&TEXT(FILTER(B4:B, B4:B<>""), "00000"), B4:B}, 2),
VLOOKUP(D4:D&TEXT(E4:E, "00000"), {A4:A&TEXT(FILTER(B4:B, B4:B<>""), "00000"), B4:B}, 2), 0)))
我用过
=ArrayFormula(VLOOKUP(D4:D8&text(E4:E8,"0000"),A4:A10&text(B4:B10,"0000"),1,true))
从 J4 开始
然后
=ArrayFormula(if(--left(J4:J8)=D4:D8,--right(J4:J8,4),""))
从 K4 开始。
需要进一步细化,但不对前一组的最大值做出任何假设。
编辑
所以在进一步工作之后它看起来像这样
=ArrayFormula(if(D4:D="",,
if(D4:D=
vlookup(D4:D&text(E4:E,"0000"),filter({A4:A&text(B4:B,"0000"),A4:A},A4:A<>""),2,true),
vlookup(D4:D&text(E4:E,"0000"),filter({A4:A&text(B4:B,"0000"),B4:B},A4:A<>""),2,true),"")))
实际上很像@player0 的解决方案。
我想你可以通过做一些像
这样的事情让它更通用一点=text(B4,rept("0",ceiling(log10(max(B4:B)))))
假设这些都是正整数。
替代方法
我认为这是更好的方法。找出每组的起始行,以及该组中有多少行 r 小于或等于所需的 group/value 对。然后就是从组的第一行往前走r-1行,找到匹配的值:
=ArrayFormula(if(countifs(A4:A,D4:D,B4:B,"<="&E4:E)>0,
vlookup(
vlookup(D4:D,{A4:A,row(A4:A)},2,false)+countifs(A4:A,D4:D,B4:B,"<="&E4:E)-1,{row(A4:A),B4:B},2,false),))
当然假设主数据是按组和值排序的——否则你将不得不使用 sort():
=ArrayFormula(if(countifs(A4:A,D4:D,B4:B,"<="&E4:E)>0,
vlookup(
vlookup(D4:D,{sort(A4:A,A4:A,1,B4:B,1),row(A4:A)},2,false)+countifs(A4:A,D4:D,B4:B,"<="&E4:E)-1,{row(A4:A),SORT(B4:B,A4:A,1,B4:B,1)},2,false),))