匹配两个csv列(fuzzy?)并提取行信息

fhg3lkii  于 2023-02-27  发布在  其他
关注(0)|答案(1)|浏览(166)

我有两个csv文件与一些1k的条目,每个像这样:

#1.csv
Org,Address,Phone
George, 121 faraday street, 837-837
Newton, 837 Bohr Street, 8327-837
...
#2.csv
Org,location,course
George William, Paris, Engineering
P Newton, London, Arts
...

基本上,2.csv的第1列包含1.csv的第1列中的名称的一些细微变化(主要是打字错误)。
我希望生成如下所示的输出(将相应的location元素从2.csv添加到1.csv):

#result.csv
Org,Address,Phone
George, 121 faraday street, 837-837, Paris
Newton, 837 Bohr Street, 8327-837, London
...

当然,匹配不会是完美的,因为它可能是模糊的,但我想知道什么是最好的方法来处理这一点。bash或python都可以,因为目标系统有这些。
我当时的想法是逃跑:

for i in entry:
    <match i to all entries on 2.csv>
    <get matching row>
    <add row to column>

但是我怎么能做到呢?因为我不知道什么是最好的匹配方式。

6yoyoihd

6yoyoihd1#

正如一些人所说,fuzzy匹配的含义是(* 请原谅双关语 *)模糊的!
只要file 1中的surnames是唯一的,也就是说 * 任何给定的姓只有一行 ,这就能满足您的需要。
假设file 1只有surname,而您要匹配的是file 2中一组不是“ambiguous”的名称(
既用作名字也用作姓氏的名称没有交叉 *),那么此脚本中实现的逻辑将为您提供一个解决方案。
正如一些人所说,如果您在file 1 * 中的姓氏可以与file 2 * 中的姓氏或名字匹配,而您希望这样,那么您必须添加逻辑来拆分file 2的第一个字段,并检查所需的元素以与file 1的姓氏匹配。

脚本:

#!/bin/bash

file1="contact.csv"
cat >"${file1}" <<"EnDoFiNpUt"
Org,Address,Phone
George, 121 faraday street, 837-837
Newton, 837 Bohr Street, 8327-837
Isayevich, #169 - Tverskaya 12, 878-979 
EnDoFiNpUt

file2="events.csv"
cat >"${file2}" <<"EnDoFiNpUt"
Org,location,course
George William, Paris, Engineering
P Newton, London, Arts
Aleksandr Isayevich Solzhenitsyn, Troitse-Lykovo, Literature
EnDoFiNpUt    

### Desired Output
file3="eventContact.csv"
#Org,Address,Phone
#George, 121 faraday street, 837-837, Paris
#Newton, 837 Bohr Street, 8327-837, London

awk -v dbg=1 -v f1="${file1}" '\
BEGIN{
    split("", eventContact )
    indexE=0 ;
    while( getline < f1 ){
        indexE++ ;
        n=split($0, tmp, "," ) ;
        for( j=1 ; j <= n ; j++ ){
            eventContact[indexE,j]=tmp[j] ;
            if( dbg == 1 ){ print "\t|", indexE, j, eventContact[indexE,j] ; } ;
        } ;
    } ;
    split("", event) ;
    if( dbg == 1 ){ print "\t|-- End of initialization --\n" ; } ;
}
{
    if( NR > 1 ){
        split($0, event, "," ) ;
        if( dbg == 1 ){ print "\t|", event[1] ; } ;

        m=split(event[1], names ) ;

        nMatch=0 ;
        for( k=1 ; k <= m ; k++ ){
            for( i=2 ; i <= indexE ; i++ ){
                if( dbg == 1 ){ print "\t|\t", eventContact[i,1] ; } ;

                #if( index( event[1], eventContact[i,1] ) != 0 ){
                #if( eventContact[i,1] ~ event[1] ){
                if( names[k] ~ eventContact[i,1] ){
                    if( dbg == 1 ){ print "\t|\t\t", event[2] ; } ;
                    eventContact[i,4]=event[2] ;
                    nMatch=1 ;
                    break ;
                } ;
            } ;
            if( nMatch == 1 ){ break ; } ;
        } ;
    } ;
}
END{
    if( dbg == 1 ){ print "\t|-- End of match-making --\n" ; } ;
    eventContact[1,4]="Location" ;

    for( i=1 ; i <= indexE ; i++ ){
        printf("%s,%s,%s,%s\n", eventContact[i,1], eventContact[i,2], eventContact[i,3], eventContact[i,4] ) ;
    } ;
}' "${file2}"   #>"${file3}"

输出(dbg=1):

| 1 1 Org
    | 1 2 Address
    | 1 3 Phone
    | 2 1 George
    | 2 2  121 faraday street
    | 2 3  837-837
    | 3 1 Newton
    | 3 2  837 Bohr Street
    | 3 3  8327-837
    | 4 1 Isayevich
    | 4 2  #169 - Tverskaya 12
    | 4 3  878-979 
    |-- End of initialization --

    | George William
    |    George
    |         Paris
    | P Newton
    |    George
    |    Newton
    |    Isayevich
    |    George
    |    Newton
    |         London
    | Aleksandr Isayevich Solzhenitsyn
    |    George
    |    Newton
    |    Isayevich
    |    George
    |    Newton
    |    Isayevich
    |         Troitse-Lykovo
    |-- End of match-making --

Org,Address,Phone,Location
George, 121 faraday street, 837-837, Paris
Newton, 837 Bohr Street, 8327-837, London
Isayevich, #169 - Tverskaya 12, 878-979 , Troitse-Lykovo

相关问题