Pyspark 如何使用Spark在另一个数据集中查找高度相似的观测值

Pyspark 如何使用Spark在另一个数据集中查找高度相似的观测值,pyspark,apache-spark-sql,Pyspark,Apache Spark Sql,我有两个csv文件。文件1: D,FNAME,MNAME,LNAME,GENDER,DOB,snapshot 2,66M,J,Rock,F,1995,201211.0 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,

我有两个csv文件。文件1:

D,FNAME,MNAME,LNAME,GENDER,DOB,snapshot
2,66M,J,Rock,F,1995,201211.0
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
文件2:

PID,FNAME,MNAME,LNAME,GENDER,DOB,FNAMELNAMEMNAMEGENDERDOB
S2,66M,J,Rock,F,1995,66MRockJF1995
S3,David,HM,Lee,M,1990,DavidLeeHMM1990
S0,Marc,HM,Robert,M,2000,MarcRobertHMM2000
S1,Marc,MS,Robert,M,2000,MarcRobertMSM2000
S6,Paul,Row,M,2008,PaulRowM2008
S7,Sam,O,Baby,F,2018,SamBabyOF2018

例如,我想用文件1中的MarcHRobertM2000提取文件2中高度相似的观察结果。 我的预期产出将是:

S0,Marc,HM,Robert,M,2000,MarcRobertHMM2000
S1,Marc,MS,Robert,M,2000,MarcRobertMSM2000
我使用了以下代码:

sqlContext.registerDataFrameAsTable(df2,'table')
query=""" SELECT PID, FNAMELNAMEMNAMEGENDERDOB, similarity(lower(FNAMELNAMEMNAMEGENDERDOB), 'MarcHRobertM2000') as sim
    FROM table
    WHERE sim>0.7 """
df=sqlContext.sql(query)


看起来SQL中的
相似性在sqlcontext中不起作用。我不知道如何修理它。另外,文件2很大,大约5GB,所以我没有在python中使用
fuzzywyzy
。而且,
soundex
并不令人满意。你能帮我吗?多谢各位

您可以使用Levenshtein距离函数来检查相似性

请参考以下代码

query=""" SELECT PID, FNAMELNAMEMNAMEGENDERDOB, levenshtein(FNAMELNAMEMNAMEGENDERDOB, 'MarcHRobertM2000') as sim
    FROM table
    WHERE sim < 4 """
query=“”选择PID、FNAMELNAMEMNNAMEGENDERDOB、levenshtein(FNAMELNAMEMNNAMEGENDERDOB,‘MarcHRobertM2000’)作为sim卡
从桌子上
其中sim<4“”

另外,请检查阅读是否正确。

谢谢。看起来我们只能使用soundex或levenshtein。但是levenshtein在识别字母和数字混合的字符串方面有一周的时间。例如,这里提到的距离btw str99='99 Broadway',str100='100 Broadway',str999='999 Broadway',我建议您分别比较
Gender
dob
,对于姓名+地址,使用regexp_extract()查找第一个数字并将其保存为一列(即街道编号),然后根据
sim<4和其他条件进行比较,其他条件包括性别、出生日期、街道号码(根据您处理空值的方式,条件可以是a.dob b.dob或任何出生日期为空等)。@jxc谢谢您。我还考虑了将
Gender
dob
信息分开。在我的数据中,有许多OB在
Gender
中没有空值。我试图写一个语句,该连接保证
Gender
是完全匹配的,或者一方有空值,
df7=df2.join(df5,(levenshtein(df2.fnamelname,df5.fnamelname)<4)和(df2.Gender==df5.Gender | df2.Gender==“df5=”)
。但它不起作用。
a.dob.dob
是否意味着
dob
可以更大或更小?我搜索了一下,但没有找到答案。@Samson,
(在SQL上下文中使用)与
=
相同,只是当两边都为NULL时它返回true(类似于df.column.eqNullSafe()),而
=
返回NULL并且总是失败。您可能可以尝试添加:
coalesce(df1.dob,df2.dob).eqNullSafe(coalesce(df2.dob,df1.dob))
以在
dob
相同或缺少一个或两个(NULL)时生成一个条件。例如,在Spark SQL上下文中,使用:
df.where('coalesce(a.dob,b.dob)coalesce(b.dob,a.dob)
。或者以长格式:
df.where('a.dob b.dob或a.dob为NULL或b.dob为NULL')