Pyspark 按相同顺序对至少具有两个相同描述符的案例进行分组

Pyspark 按相同顺序对至少具有两个相同描述符的案例进行分组,pyspark,Pyspark,我有以下数据帧: +--------+--------------------+ | id| description| +--------+--------------------+ |14144206|(1.0, 0.0, 0.0, 0.0)| |14144206|(0.0, 1.0, 0.0, 0.0)| |19461601|(0.0, 0.0, 1.0, 0.0)| |19461601|(0.0, 0.0, 0.0, 1.0)| |34578543|(1.0, 0

我有以下数据帧:

+--------+--------------------+
|      id|         description|
+--------+--------------------+
|14144206|(1.0, 0.0, 0.0, 0.0)|
|14144206|(0.0, 1.0, 0.0, 0.0)|
|19461601|(0.0, 0.0, 1.0, 0.0)|
|19461601|(0.0, 0.0, 0.0, 1.0)|
|34578543|(1.0, 0.0, 0.0, 0.0)|
|34578543|(0.0, 1.0, 0.0, 0.0)|
|45672467|(0.0, 1.0, 0.0, 0.0)|
|45672467|(0.0, 0.0, 1.0, 0.0)|
|45672467|(0.0, 0.0, 0.0, 1.0)|
+--------+--------------------+
可通过以下代码获得:

df = sqlCtx.createDataFrame(
    [
        (14144206, '(1.0, 0.0, 0.0, 0.0)'),
        (14144206, '(0.0, 1.0, 0.0, 0.0)'),
        (19461601, '(0.0, 0.0, 1.0, 0.0)'),
        (19461601, '(0.0, 0.0, 0.0, 1.0)'),
        (34578543, '(1.0, 0.0, 0.0, 0.0)'),
        (34578543, '(0.0, 1.0, 0.0, 0.0)'),
        (45672467, '(0.0, 1.0, 0.0, 0.0)'),
        (45672467, '(0.0, 0.0, 1.0, 0.0)'),
        (45672467, '(0.0, 0.0, 0.0, 1.0)')
            ],
    ('id', 'description')
)
所需的输出是一个元组列表(长度可以是2、3,最长可达长度(描述)),其中每个元组包含在列描述中以相同顺序出现2次、3次、4次等的id。所以这里的输出应该是:

[(14144206, 34578543), (34578543, 45672467)]
第一步是按id分组并对描述求和,以获得以下数据帧:

+--------+--------------------+
|      id|         description|
+--------+--------------------+
|14144206|(1.0, 1.0, 0.0, 0.0)|
|19461601|(0.0, 0.0, 1.0, 1.0)|
|34578543|(1.0, 1.0, 0.0, 0.0)|
|45672467|(0.0, 1.0, 1.0, 1.0)|
+--------+--------------------+
但是,我在执行此指令时遇到以下错误:

df.groupBy("id").agg(sum("description").alias("sum_description"))

Error :"cannot resolve 'sum(`description`)' due to data type mismatch: function sum requires numeric types, not org.apache.spark.ml.linalg.VectorUDT@3bfc3ba7
然后对于分组任务,我看不出是否存在用于此目的的现有函数


作为参考,我的真实数据帧的列描述长度为35000,并且有大约15000个不同的id

不确定我是否遵循了逻辑,因为我得到了一个稍微不同的答案,但下面是:

# Find the cardinality of each description
description_cnt=df.groupby('description').agg(f.sum(f.lit(1)).alias('id_cnt'))
df=df.join(description_cnt, on='description')

# Group by description and count and gather the Id's into a list
df_id_grp=df.groupby('description','id_cnt')
             .agg(f.collect_list('id')
             .alias('grouped_id'))

# Filter down to count 2 and display
df_id_grp.filter(df_id_grp['id_cnt']==2)
         .select('grouped_id')
         .rdd.map(lambda x: tuple(x['grouped_id']))
         .take(20)

如你所见,答案与你的不同,但我认为逻辑与你所描述的一样。如果您能回顾一下并让我知道您的想法,我会相应地进行修改。

谢谢,我不知道collect_list()函数是否真正有用。基本上,通过您的代码,我得到了每个级别的描述的id列表。我看到两个缺点:首先,结果太大,因为缺少一个条件,即两个id在两个不同的组中至少出现两次时才分组。其次,过滤条件“df_id_grp['id_cnt']==2”阻止收集以3人或更多人为一组出现的id OK,当我有空闲时间时,会将该条件添加到代码中。第二个条件是不必要的,只是尝试匹配您给出的示例输出。我的想法如下:对于每个级别的描述,我们都有具有此级别的id列表。我想考虑以下条件:对于所有级别的描述,对于所有可能具有该级别的夫妇,我们是否在另一个级别的描述中找到这对夫妇。对于所有的三元组也是一样:对于每个至少有3个id的级别,我们是否在另一个级别的描述中找到这个三元组