连接两列pyspark数据帧时获取唯一值

时间:2018-06-16 00:23:23

标签: python apache-spark pyspark

我在pyspark中有一个数据框,如下所示。

+---+-------------+------------+
| id|       device|       model|
+---+-------------+------------+
|  3|      mac pro|         mac|
|  1|       iphone|     iphone5|
|  1|android phone|     android|
|  1|   windows pc|     windows|
|  1|   spy camera|  spy camera|
|  2|             |      camera|
|  3|         cctv|        cctv|
|  2|       iphone|apple iphone|
|  3|   spy camera|            |
+---+-------------+------------+

我想通过在每个column的{​​{1}}列中连接唯一值来创建device and model

我在下面做了

首先连接两个id

device and model

然后按df1 = df.select(col("id"), concat(col("model"), lit(","), col("device")).alias('con')) +---+--------------------+ | id| con| +---+--------------------+ | 3| mac,mac pro| | 1| iphone5,iphone| | 1|android,android p...| | 1| windows,windows pc| | 1|spy camera,spy ca...| | 2| camera,| | 3| cctv,cctv| | 2| apple iphone,iphone| | 3| ,spy camera| +---+--------------------+

完成了groupBy
id

但我在结果中得到重复的值。如何避免在最终数据框中填充重复值

3 个答案:

答案 0 :(得分:2)

您可以使用collect_setudf功能删除重复项

from pyspark.sql import functions as f
from pyspark.sql import types as t

def uniqueStringUdf(device, model):
    return ','.join(set(filter(bool, device + model)))

uniqueStringUdfCall = f.udf(uniqueStringUdf, t.StringType())

df.groupBy("id").agg(uniqueStringUdfCall(f.collect_set("device"), f.collect_set("model")).alias("con")).show(truncate=False)

应该给你

+---+------------------------------------------------------------------+
|id |con                                                               |
+---+------------------------------------------------------------------+
|3  |spy camera,mac,mac pro,cctv                                       |
|1  |spy camera,windows,iphone5,windows pc,iphone,android phone,android|
|2  |camera,iphone,pple iphone                                         |
+---+------------------------------------------------------------------+

其中,
device + model是两个收集集的串联 filter(bool, device + model)正在从连接列表中删除空字符串
set(filter(bool, device + model))删除连接列表中的重复字符串
','.join(set(filter(bool, device + model)))将连接列表的所有元素连接到以逗号分隔的字符串。

我希望答案很有帮助

答案 1 :(得分:2)

使用F.array()F.explode()F.collect_set()

from pyspark.sql import functions as F

df.withColumn('con', F.explode(F.array('device', 'model')))   \
  .groupby('id').agg(F.collect_set('con').alias('Group_con')) \
  .show(3,0)

# +---+--------------------------------------------------------------------------+
# |id |Group_con                                                                 |
# +---+--------------------------------------------------------------------------+
# |3  |[cctv, mac pro, spy camera, mac]                                          |
# |1  |[windows pc, iphone5, windows, iphone, android phone, spy camera, android]|
# |2  |[apple iphone, camera, iphone]                                            |
# +---+--------------------------------------------------------------------------+

(在火花版2.2.1上测试)

答案 2 :(得分:0)

不确定这是否会非常有用。但我能想到的一个解决方案是检查列中的重复值,然后使用它们的位置/索引删除它们。

将所有值拆分为逗号","列出并通过比较每个值删除所有重复项。或者count()一个值的出现,如果它超过1,则删除除第一个之外的所有重复项。

很抱歉,如果这没有帮助。这是我能想到解决问题的两种方法。