我在Excel中有两张不同的纸张,包含300,000个数据。 第一张包含:
S2_Symbol Start_Pos End Position
STE 254857 267891
PRI 748578 758962
ILA 852741 963369
VIS 789456 796325
第二
S1_Location
789460
852898
748678
我的输出应该是这样的:
S1_Location Symbol
789460 VIS
852898 ILA
748678 PRI
我必须发现S1_location
落在S2_location
及其相应的符号中。我在Excel中使用了INDEX公式但是对于每个单元格,我必须手动更改参考单元格。我无法做到300,000个数据。
如何在Excel中使用或者我应该使用脚本?
答案 0 :(得分:2)
此解决方案假设如下:
每个S2 Symbol
的开始和结束位置都是唯一的(即分配给每个符号的范围之间没有交集)
第一张表格中的数据位于A1:D17
(根据需要调整公式中的范围)
A1:B300010
(根据需要调整公式中的范围) 解决方案要求:
图。 1
然后在第二个工作表中输入此公式B2
并复制到最后一个记录。
=INDEX( Sheet1!$A$1:$A$17,
SUMIFS( Sheet1!$D$1:$D$17,
Sheet1!$B$1:$B$17, "<=" & $A2, Sheet1!$C$1:$C$17, ">=" & $A2 ) )
图。 2
它采取了aprox。向下复制并计算表2中的公式不到14秒。 如图1和图2所示,不需要对表格进行排序。
答案 1 :(得分:1)
假设两张纸都在A1中开始,而第一张纸ColumnB按升序排序,请在第二张B2中尝试:
=INDEX(First!A:A,MATCH(A2,First!B:B))
复制到西装。它依赖于不精确的匹配。
答案 2 :(得分:1)
假设我们有Sheet1
这样:
请注意,Sheet1
按Start_Pos
,End_Pos
按升序排序。
和Sheet2
这样:
然后Sheet2!B2
向下的公式可能是:
=INDEX(Sheet1!A:A,IF(MATCH(A2,Sheet1!B:B)>IFERROR(MATCH(A2-(10^-10),Sheet1!C:C),0),MATCH(A2,Sheet1!B:B),NA()))
请参阅MATCH
:https://support.office.com/en-us/article/MATCH-function-e8dffd45-c762-47d6-bf89-533f4a37673a
这个想法是:MATCH
没有完全匹配(没有参数match_type
)获取最大值的行,该值小于或等于搜索值。因此,在Start_Pos
列中,它将获得我们可以从中获取S2_Symbol
的行。但是,如果值不在给定范围之外,则应从End_Pos
列预先获得一行。
只有一个例外。如果该值与End_Pos
列中的值完全相同,则它将返回与Start_Pos
列中相同的行。考虑到此异常,我们可以在End_Pos
列中搜索稍微小一点的值。感谢Tom Sharpe的评论。
Sheet2!D2
向下的公式是:
{=INDEX(Sheet1!A:A,MIN(IF($A2>=Sheet1!$B$2:$B$300000,IF($A2<=Sheet1!$C$2:$C$300000,ROW(Sheet1!$A$2:$A$300000),2^20+1))))}
这是一个根据要求精确制定的数组公式。但是在很多细胞中使用这种性能非常糟糕。但是使用它,Sheet1
不需要排序。
基准测试:
拥有以下Sheet1
:
公式:
A2:A300002
:="S"&(ROW(A1)-1)*10&"-"&(ROW(A1)-1)*10+7
B2:B300002
:=(ROW(A1)-1)*10
C2:C300002
:=B2+7
以及以下Sheet2
:
公式:
A2:A300002
:=RANDBETWEEN(0,3000007)
B2:B300002
:=INDEX(Sheet1!A:A,IF(MATCH(A2,Sheet1!B:B)>IFERROR(MATCH(A2-10^-9,Sheet1!C:C),0),MATCH(A2,Sheet1!B:B),NA()))
请注意先前版本中的-10^-9
而不是-10^-10
。这是因为我们只有16位精度。在以前的版本中,这是最多6位整数部分,然后是10位小数部分。现在它是最大7位整数部分,然后是9位小数部分。
在F9
中按Sheet2
后计算需要大约2秒(Excel 2007,Windows 7,4核处理器)。
答案 3 :(得分:0)
我会选择这样的东西,如果有的话,会给你第一场比赛: -
=INDEX(First!A:A,MATCH(1,(First!B:B<=A2)*(First!C:C>=A2),0))
假设键和起始值和结束值位于名为First的表单中,查找值从A2开始。
必须使用 Ctrl Shift 输入
输入的数组公式在回答@pnuts关于需要多长时间的问题时,我已经建立了一个类似的基准,每张表有300,000行,90分钟后已经达到1%,所以它需要大约150个小时才能到达100%或大约一周。这是预期的,因为所需的计算次数是(表1中的行)X(表2中的行)
300,000 X 300,000
但实际上因为乘法适用于完整列,我相信它更正确
300,000 X 1,048,576
即。 &GT; 3000亿。
对较小范围给出良好响应的实用版本如下: -
我定义了三个命名范围Range1,Range2和Range3
=First!$A$1:INDEX(First!$A:$A,MATCH("ZZZ",First!$A:$A))
=First!$B$1:INDEX(First!$B:$B,MATCH(9.9E+307,First!$B:$B))
=First!$C$1:INDEX(First!$C:$C,MATCH(9.9E+307,First!$C:$C))
,修改后的公式为
=INDEX(Range1,MATCH(1,(Range2<=A2)*(Range3>=A2),0))
我正在考虑删除这个答案,但我宁愿把它作为一个反例。