如何在Pyspark中为数据帧上的不同组找到不同的值并重新编码数据帧
我有一个大的数据框,数据框包含一群人,他们在变量“groups”中被标记 我现在需要为这个数据帧做的是以一种更有意义的方式呈现 例如,在以下148组中,下表如下:如何在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
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”)感谢您的帮助!