我正在尝试对Spark数据帧进行重复数据删除,仅保留最新的外观。 重复项包含三个变量:
NAME
ID
DOB
我成功实现了以下成就:
df_dedupe = df.drop_duplicates(subset=['NAME','ID','DOB'], keep='last', inplace=False)
但是在火花中,我尝试了以下操作:
df_dedupe = df.dropDuplicates(['NAME', 'ID', 'DOB'], keep='last')
我收到此错误:
TypeError: dropDuplicates() got an unexpected keyword argument 'keep'
有什么想法吗?
答案 0 :(得分:1)
感谢您的帮助。 我遵循了您的指示,但结果与预期不符:
WriteBlob Failed `/path/to/1-607405443.png' @ error/png.c/MagickPNGErrorHandler/1726
[app/controller/web/fax.php:1044] Imagick->writeimage('/path/to/1-607405443.png')
结果是:
d1 = [('Bob', '10', '1542189668', '0', '0'), ('Alice', '10', '1425298030', '154', '39'), ('Bob', '10', '1542189668', '178', '42')]
df1 = spark.createDataFrame(d1, ['NAME', 'ID', 'DOB' , 'Height' , 'ShoeSize'])
df_dedupe = df1.dropDuplicates(['NAME', 'ID', 'DOB'])
df_reverse = df1.sort((["NAME", "ID", "DOB"]), ascending= False)
df_dedupe.join(df_reverse,['NAME','ID','DOB'],'inner')
df_dedupe.show(100, False)
显示带有损坏数据的“鲍勃”。
最后,我改变了方法,将DF转换为Pandas,然后又恢复了火花:
+-----+---+----------+------+--------+
|NAME |ID |DOB |Height|ShoeSize|
+-----+---+----------+------+--------+
|Bob |10 |1542189668|0 |0 |
|Alice|10 |1425298030|154 |39 |
+-----+---+----------+------+--------+
这终于带来了正确的“鲍勃”:
p_schema = StructType([StructField('NAME',StringType(),True),StructField('ID',StringType(),True),StructField('DOB',StringType(),True),StructField('Height',StringType(),True),StructField('ShoeSize',StringType(),True)])
d1 = [('Bob', '10', '1542189668', '0', '0'), ('Alice', '10', '1425298030', '154', '39'), ('Bob', '10', '1542189668', '178', '42')]
df = spark.createDataFrame(d1, p_schema)
pdf = df.toPandas()
df_dedupe = pdf.drop_duplicates(subset=['NAME','ID','DOB'], keep='last', inplace=False)
df_spark = spark.createDataFrame(df_dedupe, p_schema)
df_spark.show(100, False)
当然,我仍然希望有一个纯粹的Spark解决方案,但是缺少索引似乎对Spark来说是个问题。
谢谢!
答案 1 :(得分:0)
如您在http://spark.apache.org/docs/2.1.0/api/python/pyspark.sql.html中看到的函数dropDuplicates(subset=None)
的文档所示,它仅允许子集作为参数。如果它们都相等,为什么还要保留最后一个?
编辑
正如@ W-B所指出的,您想要其他列。我的解决方案是按相反的顺序对原始数据帧进行排序,并在三个重复的列上使用df_dedupe
进行内部联接,只保留最后一个值。
df_dedupe.join(original_df,['NAME','ID','DOB'],'inner')