我有一个如下所示的 spark 数据框:
User Item Purchased
1 A 1
1 B 2
2 A 3
2 C 4
3 A 3
3 B 2
3 D 6
only showing top 5 rows
每个用户都有一行表示他们购买的商品。假设 Purhcased 是多少数量。购买(计数)。
但是,有些商品用户可能没有购买,因此对于该商品,特定用户没有一行。我们只有用户购买的商品的行。因此,如果用户 1 购买了商品 A、B,则用户 1 有 2 行对应于这两个商品。但是,如果用户 2 购买了 A、C,则用户 2 拥有商品 A 和 C 的行,但没有商品 B。我希望最后每个用户都应该拥有表中所有商品的所有行以及每个商品的相应计数。
我想将这个数据框转换成上面的数据框,但也有用户没有看到的项目行,并将相应的计数设为零。
如下所示:
User Item Purchased
1 A 1
1 B 2
1 C 0
1 D 0
2 A 3
2 C 4
2 B 0
2 D 0
3 A 3
3 B 2
3 D 6
3 C 0
only showing top 5 rows
我想到的一种方法是,如果我在第一个数据帧上使用 sqlContext 的 cross_tab 方法,那么我可以将每一行转换为具有相应值的列。对于用户没有的项目,它将为相同的项目创建一个列并将零放在那里。
但是如何将这些列转换回行呢?这也可能是一种迂回的方式。
谢谢
请您参考如下方法:
我们也可以通过仅使用 df 函数来实现这一点。
orders = [(1,"A",1),(1,"B",2),(2,"A",3),(2,"C",4),(3,"A",3),(3,"B",2),(3,"D",6)]
df = sqlContext.createDataFrame(orders, ["user","item","purchased"])
df_items = df.select("item").distinct().repartition(5).withColumnRenamed("item", "item_1")
df_users = df.select("user").distinct().repartition(5).withColumnRenamed("user", "user_1")
df_cartesian = df_users.join(df_items)
//above expression returns cartesian product of users and items dfs
joined_df = df_cartesian.join(df, [df_cartesian.user_1==df.user, df_cartesian.item_1==df.item], "left_outer").drop("user").drop("item")
result_df = joined_df.fillna(0,["purchased"]).withColumnRenamed("item_1", "item").withColumnRenamed("user_1", "user")
最后,result_df.show() 产生如下所示的期望输出:
+----+----+---------+
|user|item|purchased|
+----+----+---------+
| 2| A| 3|
| 2| B| 0|
| 2| C| 4|
| 2| D| 0|
| 3| A| 3|
| 3| B| 2|
| 3| C| 0|
| 3| D| 6|
| 1| A| 1|
| 1| B| 2|
| 1| C| 0|
| 1| D| 0|
+----+----+---------+
