Совпадение двух CSV на основе сопоставления с образцом в одном столбце - PullRequest
0 голосов
/ 10 мая 2019

У меня есть два файла CSV в следующих форматах:

==

FirstName | LastName | Email
Steven | Smith | stevesmith1@gmail.com
Jane | Brown | jb155@yahoo.com
Paul | Gibson | paulgibbs@outlook.com

==

ID | FirstName | LastName | IncompleteEmail
1028332982 | Steven | Smith | s*****1@g*l.com
1028820233 | Jane | Brown | j******n@yahoo.com
934943823 | Paul | Gibson | p*****s@h****l.com

==

Я бы хотел сопоставить два CSV-файла на этой основе - если FirstName и LastName совпадают, Email в первом CSV соответствует шаблону IncompleteEmail во втором CSV должен быть создан вывод, содержащий ID | Email

В приведенном выше примере результат будет выглядеть следующим образом:

ID | Email
1028332982 | stevesmith1@gmail.com

Причина этого в том, что «Стив» и «Смит» одинаковы в обоих CSV, а шаблон IncompleteEmail соответствует электронной почте. Другие входные данные не совпадают, так как шаблон IncompleteEmail не соответствует электронной почте.

Ранее я использовал сценарий join (например, join -i -t '|' -j 1 -o 2.2,2.3 1.txt 2.txt > out.txt) для обработки похожих файлов, но я не знаю, как изменить сценарий объединения для работы с шаблоном вместо точного соответствия. Я знаю, что подобный подход возможен и в AWK, но я открыт для предложений.

Нужно что-то, что может работать с большими входами (два CSV по 10 миллионов + строк в каждом).

Заранее спасибо.

Ответы [ 3 ]

1 голос
/ 10 мая 2019

Предполагая, что вы хотите, чтобы любое повторение * s обрабатывалось так же, как .* обрабатывается в регулярном выражении, а каждый другой метасимвол RE (например, .) обрабатывается буквально, а ^ может ' т происходит в адресе электронной почты:

$ cat tst.awk
BEGIN { FS=" [|] "; OFS=" | " }
FNR==1 {
    for (i=1; i<=NF; i++) {
        f[$i] = i
    }
}
{ name = $(f["FirstName"]) FS $(f["LastName"]) }
NR==FNR {
    name2fullEmail[name] = $(f["Email"])
    next
}
FNR==1 {
    print "ID", "Email"
    next
}
name in name2fullEmail {
    fullEmail = name2fullEmail[name]
    partEmail = $(f["IncompleteEmail"])
    gsub(/./,"[&]",partEmail)
    gsub(/[[][*][]]/,".*",partEmail)
    if (fullEmail ~ "^"partEmail"$") {
        print $(f["ID"]), fullEmail
    }
}

$ awk -f tst.awk file1 file2
ID | Email
1028332982 | stevesmith1@gmail.com
0 голосов
/ 10 мая 2019

Еще один в awk:

$ awk -F" [|] " -v OFS="|" '   # set field separators
NR==FNR {                      # process first file
    a[$1 OFS $2]=$3            # hash email, use name as key
    next
}
((i=$2 OFS $3) in a) {         # process second file
    gsub(/\./,"\\.",$4)        # escaping:      . -> \.
    gsub(/\*+/,".*",$4)        #           *{1,n} -> .*
    if(FNR==1 || a[i]~$4)      # if header record or regex match
        print $1,a[i]          # then output
}' file1 file2                 # mind the order

Вывод:

ID|Email
1028332982|stevesmith1@gmail.com

При обработке второго файла file2 gsub(/\*+/,".*",$4) пытается сделать регулярное выражение электронной почты ish : s*****1@g*l.com -> s.*1@g.*l\.com.При условии, что в данных образца не было никаких других мета-символов regex, кроме * и ., но другие (например, +), вероятно, тоже следует экранировать, чтобы избежать ложных совпадений, но я не совсем уверен, что у вас есть для них особое значение, напримеру вас было для *.

Кроме того, он не допустит дублирования имен в file1.Последний экземпляр выигрывает.

0 голосов
/ 10 мая 2019

Я считаю ваш первый csv файл df1, а второй csv df2.Итак, вы можете попробовать это:

import pandas as pd
import re

df_new = pd.merge(df1,df2, on=['FirstName','LastName'], how='inner')
mails = []
regex = "((\w{1})\D.*(\w{1}\@\w{1})\D.*(\w{1}[\.]\D.+)"
for d in range(len(df_new)):
    inmail = re.findall(regex,df_new.iloc[d]["IncompleteEmail"])
    commail = re.findall(regex,df_new.iloc[d]["Email"])
    if inmail == commail:
        mails.append([df_new.iloc[d]['ID'],df_new.iloc[d]["Email"]])
pd.DataFrame(mails, columns=["ID","Email"])

Вывод:

           ID                  Email
0  1028332982  stevesmith1@gmail.com
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...