如何在Pyspark中为数据帧上的不同组找到不同的值并重新编码数据帧

如何在Pyspark中为数据帧上的不同组找到不同的值并重新编码数据帧,pyspark,pyspark-sql,Pyspark,Pyspark Sql,我有一个大的数据框,数据框包含一群人,他们在变量“groups”中被标记 我现在需要为这个数据帧做的是以一种更有意义的方式呈现 例如,在以下148组中,下表如下: df.select('gender','postcode','age','groups','bought').filter(df.groups==148).show() +------+--------+---+----------+----------+ |gender|postcode|age| groups|bou

我有一个大的数据框,数据框包含一群人,他们在变量“groups”中被标记

我现在需要为这个数据帧做的是以一种更有意义的方式呈现

例如,在以下148组中,下表如下:

df.select('gender','postcode','age','groups','bought').filter(df.groups==148).show()   

+------+--------+---+----------+----------+
|gender|postcode|age|    groups|bought    |
+------+--------+---+----------+----------+
|     0|    2189| 25|       148|car       |
|     0|    2192| 34|       148|house     |
|     1|    2193| 37|       148|car       |
|     1|    2194| 38|       148|house     |
|     1|    2196| 54|       148|laptop    |
|     1|    2197| 27|       148|laptop    |
|     0|    2198| 44|       148|laptop    |
+------+--------+---+----------+----------+
性别为0,1,因此该组中的所有人都将更改为“人” 如果全部为1,则为女性;如果全部为0,则为男性。规则,但不适用于此组

现在的邮政编码,最低的是2189,最高的是2211,然后每个案例都会改为[2189-2198]

对于年龄来说,最低的是18岁,最高的是62岁,所以是[25-54]

对于购买,我需要检查哪些物品已经购买,这些是[汽车、房子、笔记本电脑]

因此,该组重新编码将以以下方式结束:

+------+-------------+--------+----------+------------------+
|gender|     postcode|     age|    groups|        bought    |
+------+-------------+--------+----------+------------------+
|person|[2189 - 2198]| [25-54]|       148|[car,house,laptop]|
|person|[2189 - 2198]| [25-54]|       148|[car,house,laptop]|
|person|[2189 - 2198]| [25-54]|       148|[car,house,laptop]|
|person|[2189 - 2198]| [25-54]|       148|[car,house,laptop]|
|person|[2189 - 2198]| [25-54]|       148|[car,house,laptop]|
|person|[2189 - 2198]| [25-54]|       148|[car,house,laptop]|
|person|[2189 - 2198]| [25-54]|       148|[car,house,laptop]|
+------+-------------+--------+----------+------------------+
这将对数据帧中的所有组执行

有什么想法吗? 我发现了一些类似的东西,但在scala中 提前谢谢你

希望这有帮助

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

df = sc.parallelize([
    [0, 2189, 25, 148, 'car'],
    [0, 2192, 34, 148, 'house'],
    [1, 2193, 37, 148, 'car'],
    [1, 2194, 38, 148, 'house'],
    [1, 2196, 54, 148, 'laptop'],
    [1, 2197, 27, 148, 'laptop'],
    [0, 2198, 44, 148, 'laptop']
]).toDF(('gender', 'postcode', 'age', 'groups', 'bought'))
df.show()

df1 = df.groupBy("groups").agg(f.collect_set("bought")).withColumnRenamed("collect_set(bought)","bought")
df2 = df.groupBy("groups").agg(f.min("age"), f.max("age")). \
    withColumn("age", f.concat(f.col("min(age)"), f.lit("-"), f.col("max(age)"))).select("groups","age")
df3 = df.groupBy("groups").agg(f.min("postcode"), f.max("postcode")). \
    withColumn("postcode", f.concat(f.col("min(postcode)"), f.lit("-"), f.col("max(postcode)"))).select("groups","postcode")
def modify_values(l):
    if l == [0, 1]:
        return "person"
    else:
        if l == [0]:
            return "male"
        else:
            return "female"
modified_val = f.udf(modify_values, StringType())
df4 = df.groupBy("groups").agg(f.collect_set("gender")).withColumn("gender",modified_val("collect_set(gender)")).select("groups","gender")

merged_df = df1.join(df2, "groups").join(df3, "groups").join(df4, "groups")
merged_df.show()
输出为:

+------+--------------------+-----+---------+------+
|groups|              bought|  age| postcode|gender|
+------+--------------------+-----+---------+------+
|   148|[laptop, house, car]|25-54|2189-2198|person|
+------+--------------------+-----+---------+------+


别忘了告诉我们它是否解决了您的问题

嗨,谢谢!我可以看到它的工作原理,但我注释掉了df.show()和merged_df.show(),它在7秒内运行(持续时间:0:00:06.314000),然后我自己运行“merged_df.show()”,需要:持续时间:0:07:46.214000,将近8分钟才能显示数据帧,为什么?此外,我需要相同数量的行,而不仅仅是一行。为什么这么慢?我可以修复它吗?要使行数相同,只需运行
df.join(合并的df.alias(“mdf”)、“groups”、“right”)。选择(“mdf.*).show()
。关于慢度-如果您有大量数据,那么join显然会很慢。在
merge\u df
中使用这些数据帧之前,请尝试
.cache()
例如
df1.cache()
df2.cache()
等。也许会有帮助。好吧,我试试看。但是只有show()行需要8分钟,这是因为它是一个懒惰的操作吗?仅当您要显示数据帧时,它才会合并?是的,这应该适用于非常大的数据集,可能有100万行和许多组。Dataframe与RDD有着共同的特性,比如惰性计算,并且
show()
似乎是一个动作函数(尽管
show()
不在所列动作列表中)。顺便说一句,这个解决方案可以处理任意数量的组(当然还有行!)。我刚刚创建了一个只有“购买和预测”的数据框,并运行了这个!final_df=df_bunded.join(合并的_df.alias(“fdf”),“prediction”,“left”)感谢您的帮助!