Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/apache-spark/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Dataframe 从大数据集中删除模糊重复项_Dataframe_Apache Spark_Pyspark_Apache Spark Sql_Pyspark Dataframes - Fatal编程技术网

Dataframe 从大数据集中删除模糊重复项

Dataframe 从大数据集中删除模糊重复项,dataframe,apache-spark,pyspark,apache-spark-sql,pyspark-dataframes,Dataframe,Apache Spark,Pyspark,Apache Spark Sql,Pyspark Dataframes,我有一个CSV文件,其中有许多记录。每个记录代表一个人。它有名,姓,以及其他详细信息。 我的目标是以智能的方式从这些数据中删除重复项。记录来自不同的来源,副本可能包含不同的信息。 我在下面的示例中简化了问题: df = spark.createDataFrame( [ (1, "Anna", "Smyth", "01/03", "NY"), (2, "Anna&qu

我有一个CSV文件,其中有许多记录。每个记录代表一个人。它有
,以及其他详细信息。 我的目标是以智能的方式从这些数据中删除重复项。记录来自不同的来源,副本可能包含不同的信息。 我在下面的示例中简化了问题:

df = spark.createDataFrame(
    [
        (1, "Anna", "Smyth", "01/03", "NY"), 
        (2, "Anna", "Smyth", "01/03", ""), 
        (3, "Anna", "Smyth", "01/03", "NY"),         
        (4, "Max", "Anderson", "12/04", "Boston"), 
        (5, "Max", "Anderson", "", "London"), 
        (6, "Max", "Anderson", "06/07", ""),         
        (7, "Sarah", "Nicolson", "02/09", ""), 
        (8, "Sarah", "Jonson", "", "Mexico"), 
        (9, "Sarah", "Jonson", "01/08", "Dallas"), 
    ],
    ("id", "first_name", "last_name", "birthday", "city")
)
df.show()

+---+----------+---------+--------+------+
| id|first_name|last_name|birthday|  city|
+---+----------+---------+--------+------+
|  1|      Anna|    Smyth|   01/03|    NY|
|  2|      Anna|    Smyth|   01/03|      |
|  3|      Anna|    Smyth|   01/03|    NY|
|  4|       Max| Anderson|   12/04|Boston|
|  5|       Max| Anderson|        |London|
|  6|       Max| Anderson|   06/07|      |
|  7|     Sarah| Nicolson|   02/09|      |
|  8|     Sarah|   Jonson|        |Mexico|
|  9|     Sarah|   Jonson|   01/08|Dallas|
+---+----------+---------+--------+------+
<>我想用“代码>第一个名字< /COD>和<代码> LASTYNMENT//CODE分组记录,然后做一些比较来考虑记录是否是重复的。 如果几乎没有记录有相同的
名字和
姓氏,我想检查
生日
,如果它等于-它是重复的。 如果一条或多条记录已填充
生日
,则另一条记录-不填充,它是重复的。如果两个(或多个)记录都是空的
生日
-则重复。 相比之下,我忽略了
city
字段,但在考虑重复项时,我希望留下“最富”的记录,即填充了更多字段的记录。 如果记录有相同的名字,但不同的生日-它不是重复的

例如,在上面,我想得到:

+---+----------+---------+--------+------+
| id|first_name|last_name|birthday|  city|
+---+----------+---------+--------+------+
|  1|      Anna|    Smyth|   01/03|    NY|
|  4|       Max| Anderson|   12/04|Boston|
|  6|       Max| Anderson|   06/07|      |
|  7|     Sarah| Nicolson|   02/09|      |
|  9|     Sarah|   Jonson|   01/08|Dallas|
+---+----------+---------+--------+------+
在实际问题中,我有更多的字段——大约70个,其中一些字段应该是必须匹配的,而另一些字段则不是。我需要处理的记录数量——大约1亿条。
我正在考虑使用pyspark,但任何技术都欢迎首先,您可以通过连接列
First_name#last_name#birth
来为每行创建组列
grp
,其中
birth
由分区的max替换[
First_name
last_name]
,如果它是null或空字符串:

from pyspark.sql import Window
from pyspark.sql import functions as F

w1 = Window.partitionBy("first_name", "last_name").orderBy()

df1 = df.withColumn(
    "grp",
    F.concat_ws(
        "#",
        "first_name",
        "last_name",
        F.coalesce(F.expr("nullif(birthday, '')"), F.max("birthday").over(w1))
    )
).withColumn(
    "rich_columns",
    F.array(
        *[F.col(c) for c in df.columns if c not in ["id", "first_name", "last_name"]]
    )
)

df1.show(truncate=False)
#+---+----------+---------+--------+------+--------------------+---------------+
#|id |first_name|last_name|birthday|city  |grp                 |rich_columns   |
#+---+----------+---------+--------+------+--------------------+---------------+
#|1  |Anna      |Smyth    |01/03   |NY    |Anna#Smyth#01/03    |[01/03, NY]    |
#|2  |Anna      |Smyth    |01/03   |      |Anna#Smyth#01/03    |[01/03, ]      |
#|3  |Anna      |Smyth    |01/03   |NY    |Anna#Smyth#01/03    |[01/03, NY]    |
#|7  |Sarah     |Nicolson |02/09   |      |Sarah#Nicolson#02/09|[02/09, ]      |
#|8  |Sarah     |Jonson   |        |Mexico|Sarah#Jonson#01/08  |[, Mexico]     |
#|9  |Sarah     |Jonson   |01/08   |Dallas|Sarah#Jonson#01/08  |[01/08, Dallas]|
#|4  |Max       |Anderson |12/04   |Boston|Max#Anderson#12/04  |[12/04, Boston]|
#|5  |Max       |Anderson |        |London|Max#Anderson#12/04  |[, London]     |
#|6  |Max       |Anderson |06/07   |      |Max#Anderson#06/07  |[06/07, ]      |
#+---+----------+---------+--------+------+--------------------+---------------+
生日
城市
也用于创建一个数组列
rich_columns
,该列将用于对max info不为空/null的行进行优先级排序

然后,使用上面创建的组列执行行号,并按
rich\u列的大小排序
数组:

w2 = Window.partitionBy("grp").orderBy(
    F.expr("size(filter(rich_columns, x -> nullif(x, '') is not null))").desc()
)

df2 = df1.withColumn("rn", F.row_number().over(w2)) \
    .filter("rn = 1") \
    .drop("grp", "rn", "rich_columns")

df2.show()

#+---+----------+---------+--------+------+
#| id|first_name|last_name|birthday|  city|
#+---+----------+---------+--------+------+
#|  7|     Sarah| Nicolson|   02/09|      |
#|  1|      Anna|    Smyth|   01/03|    NY|
#|  9|     Sarah|   Jonson|   01/08|Dallas|
#|  6|       Max| Anderson|   06/07|      |
#|  4|       Max| Anderson|   12/04|Boston|
#+---+----------+---------+--------+------+
在实际应用程序中,在执行此操作之前,应将列
转换为大写字母和带重音符号(如果有)