Linux中是否有基于多列的模糊匹配命令
我有两个csv文件。 文件1 文件2Linux中是否有基于多列的模糊匹配命令,linux,join,awk,levenshtein-distance,Linux,Join,Awk,Levenshtein Distance,我有两个csv文件。 文件1 文件2 PID,FNAME,MNAME,LNAME,GENDER,DOB S2,66M,J,Rock,F,1995 S3,David,HM,Lee,M,1990 S0,Marc,HM,Robert,M,2000 S1,Marc,MS,Robert,M,2000 S6,Paul,,Row,M,2008 S7,Sam,O,Baby,F,2018 我想做的是使用人行横道文件文件2,根据FNAME、MNAME、LNAME、GENDER和DOB列,在文件1中撤销这些观察值的
PID,FNAME,MNAME,LNAME,GENDER,DOB
S2,66M,J,Rock,F,1995
S3,David,HM,Lee,M,1990
S0,Marc,HM,Robert,M,2000
S1,Marc,MS,Robert,M,2000
S6,Paul,,Row,M,2008
S7,Sam,O,Baby,F,2018
我想做的是使用人行横道文件文件2,根据FNAME、MNAME、LNAME、GENDER和DOB列,在文件1中撤销这些观察值的PID。由于文件1中的观测值中的相应信息不完整,我正在考虑使用模糊匹配尽可能多地撤销其PID(当然应该考虑级别精度)。例如,文件1中FNAME“Paul”和LNAME“Row”的观测值应分配相同的PID,因为文件2中只有一个类似的观测值。但对于FNAME“Marc”和LNAME“Robert”的观测值,Marc,MS,Robert,M,2000201211.0
应分配PID“S1”、Marc,H,Robert,M,2000201211.0
PID“S0”和Marc,M,Robert,M,201211.0
或“S1”
<>我想在保持高精度的前提下尽可能多地补偿文件1的PID,我考虑了三个步骤。首先,使用命令确保当且仅当FNAME、MNAME、LNAME、GENDER和DOB中的这些信息都完全匹配时,文件1中的观察值才能分配一个PID。输出应该是
D,FNAME,MNAME,LNAME,GENDER,DOB,snapshot,PID
2,66M,J,Rock,F,1995,201211.0,S2
3,David,HM,Lee,M,,201211.0,
6,66M,,Rock,F,,201211.0,
0,David,H M,Lee,,1990,201211.0,
3,Marc,H,Robert,M,2000,201211.0,
6,Marc,M,Robert,M,,201211.0,
6,Marc,MS,Robert,M,2000,201211.0,
3,David,M,Lee,,1990,201211.0,
5,Paul,ABC,Row,F,2008,201211.0,
3,Paul,ACB,Row,,,201211.0,
4,David,,Lee,,1990,201211.0,
4,66,J,Rock,,1995,201211.0,
接下来,编写另一个命令以确保当DOB信息完全相同时,对FNAME、MNAME、LNAME、SEXT使用模糊匹配,以撤销文件1的观察值的PID,该PID在第一步中未识别。所以这两个步骤的输出应该是
D,FNAME,MNAME,LNAME,GENDER,DOB,snapshot,PID
2,66M,J,Rock,F,1995,201211.0,S2
3,David,HM,Lee,M,,201211.0,
6,66M,,Rock,F,,201211.0,
0,David,H M,Lee,,1990,201211.0,S3
3,Marc,H,Robert,M,2000,201211.0,S0
6,Marc,M,Robert,M,,201211.0,
6,Marc,MS,Robert,M,2000,201211.0,S1
3,David,M,Lee,,1990,201211.0,S3
5,Paul,ABC,Row,F,2008,201211.0,S6
3,Paul,ACB,Row,,,201211.0,
4,David,,Lee,,1990,201211.0,S3
4,66,J,Rock,,1995,201211.0,S2
在最后一步中,使用新命令对所有相关列(即FNAME、MNAME、LNAME、GENDER和DOB)进行模糊匹配,以补偿剩余观测值的PID。因此,最终输出预计为
D,FNAME,MNAME,LNAME,GENDER,DOB,snapshot,PID
2,66M,J,Rock,F,1995,201211.0,S2
3,David,HM,Lee,M,,201211.0,S3
6,66M,,Rock,F,,201211.0,S2
0,David,H M,Lee,,1990,201211.0,S3
3,Marc,H,Robert,M,2000,201211.0,S0
6,Marc,M,Robert,M,,201211.0,S1
6,Marc,MS,Robert,M,2000,201211.0,S1
3,David,M,Lee,,1990,201211.0,S3
5,Paul,ABC,Row,F,2008,201211.0,S6
3,Paul,ACB,Row,,,201211.0,S6
4,David,,Lee,,1990,201211.0,S3
4,66,J,Rock,,1995,201211.0,S2
我需要保持文件1的观察顺序,所以它必须是一种leftouter连接。因为我的原始数据大小约为100Gb,所以我想使用Linux来处理我的问题。
但是我不知道如何通过
awk
或Linux中的任何其他命令来完成最后两个步骤。有人能帮我个忙吗?谢谢。这里是GNU awk的一个尝试(使用PROCINFO[“sorted_in”]
选择最合适的候选人)。它对每个字段的file2
字段值进行散列,并将PID
附加到值上,如field[2][“66M”]=“S2”
,并对file1
中的每个记录计算PID
匹配的数量,并打印计数最大的记录:
BEGIN {
FS=OFS=","
PROCINFO["sorted_in"]="@val_num_desc"
}
NR==FNR { # file2
for(i=1;i<=6;i++) # fields 1-6
if($i!="") {
field[i][$i]=field[i][$i] (field[i][$i]==""?"":OFS) $1 # attach PID to value
}
next
}
{ # file1
for(i=1;i<=6;i++) { # fields 1-6
if($i in field[i]) { # if value matches
split(field[i][$i],t,FS) # get PIDs
for(j in t) { # and
matches[t[j]]++ # increase PID counts
}
} else { # if no value match
for(j in field[i]) # for all field values
if($i~j || j~$i) # "go fuzzy" :D
matches[field[i][j]]+=0.5 # fuzzy is half a match
}
}
for(i in matches) { # the best match first
print $0,i
delete matches
break # we only want the best match
}
}
这里的“模糊匹配”是naivisticif($i~j | | j~$i)
,但是可以用任何近似匹配算法来替换它,例如,在互联网上有一些Levenshtein距离算法的实现。罗塞塔似乎有一个
<>你没有提到大的file1
字段映射到file2
字段的版本(如注释中所述):
开始{
FS=OFS=“,”
PROCINFO[“排序在”]=“val\u num\u desc”
映射[1]=1#将file1字段映射到file2字段
图[2]=3
图[3]=4
map[4]=2
图[5]=5
图[7]=6
}
NR==FNR{#file2
太长了,读不下去了,(我的意思是:1);我的DUP目标是非站点:所以我不能添加它。看看<代码> AdgpP>代码>或代码> TE GalpP<……代码>……如果你刚刚阅读标题,就可以关闭它,但是如果你读了整个问题(我知道,TL;Dr,我几乎跳过它)。我觉得这还不够。我真的很感谢你的帮助。文件2大约有10GB。我是awk
新手,所以你介意给我解释一下field[I][$I]=field[I][$I](field[I][$I]==“”?“”:OFS)括号中内容的含义吗$1
?在split(字段[i][$i],t,FS)
中,t
和FS
表示什么?在最后一个循环中加上(匹配中的i)…
您如何确保选择最佳匹配项?因为我没有找到最佳匹配项的排序方法。我还有另一个子问题。假设文件1中的字段顺序为D、MNAME、LNAME、FNAME、GENDER、snapshot、DOB
。那么我该怎么办?嗨,我键入了您的代码,awk'[yourcode]'file2 file1
在终端中,但它不起作用。终端警告说,字段[i][$i]=字段[i][$i](字段[i][$i]==“”?“”:OFS)中的方括号格式存在语法错误$1
加上file1循环中的所有括号。您使用的是GNU awk,对吗?脚本具有多维数组,并更改了travese排序,这两个GNU awk功能。当我输入awk--help
时,它显示消息用法:awk[POSIX或GNU样式选项]-f progfile[--]file…用法:awk[POSIX或GNU样式选项][--]“程序”文件…POSIX选项:GNU长选项:….
。awk--version
怎么样?
BEGIN {
FS=OFS=","
PROCINFO["sorted_in"]="@val_num_desc"
}
NR==FNR { # file2
for(i=1;i<=6;i++) # fields 1-6
if($i!="") {
field[i][$i]=field[i][$i] (field[i][$i]==""?"":OFS) $1 # attach PID to value
}
next
}
{ # file1
for(i=1;i<=6;i++) { # fields 1-6
if($i in field[i]) { # if value matches
split(field[i][$i],t,FS) # get PIDs
for(j in t) { # and
matches[t[j]]++ # increase PID counts
}
} else { # if no value match
for(j in field[i]) # for all field values
if($i~j || j~$i) # "go fuzzy" :D
matches[field[i][j]]+=0.5 # fuzzy is half a match
}
}
for(i in matches) { # the best match first
print $0,i
delete matches
break # we only want the best match
}
}
D,FNAME,MNAME,LNAME,GENDER,DOB,snapshot,PID
2,66M,J,Rock,F,1995,201211.0,S2
3,David,HM,Lee,M,,201211.0,S3
6,66M,,Rock,F,,201211.0,S2
0,David,H M,Lee,,1990,201211.0,S3
3,Marc,H,Robert,M,2000,201211.0,S0
6,Marc,M,Robert,M,,201211.0,S1
6,Marc,MS,Robert,M,2000,201211.0,S1
3,David,M,Lee,,1990,201211.0,S3
5,Paul,ABC,Row,F,2008,201211.0,S6
3,Paul,ACB,Row,,,201211.0,S6
4,David,,Lee,,1990,201211.0,S3
4,66,J,Rock,,1995,201211.0,S2
BEGIN {
FS=OFS=","
PROCINFO["sorted_in"]="@val_num_desc"
map[1]=1 # map file1 fields to file2 fields
map[2]=3
map[3]=4
map[4]=2
map[5]=5
map[7]=6
}
NR==FNR { # file2
for(i=1;i<=6;i++) # fields 1-6
if($i!="") {
field[i][$i]=field[i][$i] (field[i][$i]==""?"":OFS) $1 # attach PID to value
}
next
}
{ # file1
for(i in map) {
if($i in field[map[i]]) { # if value matches
split(field[map[i]][$i],t,FS) # get PIDs
for(j in t) { # and
matches[t[j]]++ # increase PID counts
}
} else { # if no value match
for(j in field[map[i]]) # for all field values
if($i~j || j~$i) # "go fuzzy" :D
matches[field[map[i]][j]]+=0.5 # fuzzy is half a match
}
}
for(i in matches) { # the best match first
print $0,i
delete matches
break # we only want the best match
}
}