如何为每个组创建一个新列以指示每个用户拥有的项目数



>假设我有一个如下所示的Pyspark数据帧。每个用户在某个特定日期购买一件商品。

+--+-------------+-----------+
|ID|  Item Bought| Date      |
+--+-------------+-----------+
|1 |  Laptop     | 01/01/2018|  
|1 |  Laptop     | 12/01/2017|  
|1 |  Car        | 01/12/2018|  
|2 |  Cake       | 02/01/2018|  
|3 |  TV         | 11/02/2017| 
+--+-------------+-----------+

现在我想创建一个新的数据框,如下所示。

+---+--------+-----+------+----+
|ID | Laptop | Car | Cake | TV |
+---+--------+-----+------+----+
|1  | 2      | 1   | 0    | 0  | 
|2  | 0      | 0   | 1    | 0  |
|3  | 0      | 0   | 0    | 1  |
+---+--------+-----+------+----+
有项目列

,每列对应一个项目。对于每个用户,每列上的数字是用户购买的商品的数量。

如果你在 pyspark 中有这样的数据帧

df = sc.parallelize(([(1, 'laptop', '01/01/2018'),
                    (1, 'laptop', '12/01/2017'),
                    (1, 'car', '01/12/2018'),
                    (2, 'cake', '02/01/2018'),
                    (3, 'tv', '11/02/2017')])).toDF(['id', 'item bought', 'date'])

现在,您可以使用分组依据和透视操作来获取结果。

df2 = (df.groupby(['id']).pivot('item bought', ['tv','cake', 'laptop',"car"]).
                count().fillna(0).show())
df2.show()

结果

+---+---+----+------+---+
| id| tv|cake|laptop|car|
+---+---+----+------+---+
|  1|  0|   0|     2|  1|
|  3|  1|   0|     0|  0|
|  2|  0|   1|     0|  0|
+---+---+----+------+---+

请记住,在枢轴操作中,没有必要提供不同的值,但提供这些值将加快该过程。

另一种解决方案,

import pyspark.sql.functions as F
df = sc.parallelize([
(1,'Laptop','01/01/2018'), (1,  'Laptop','12/01/2017'),(1,'Car','01/12/2018'),
(2 ,'Cake', '02/01/2018'),(3,'TV','11/02/2017')]).toDF(['ID','Item','Date'])

items = sorted(df.select("Item").distinct().rdd
           .map(lambda row: row[0])
           .collect())
cols = [F.when(F.col("Item") == m, F.col("Item")).otherwise(None).alias(m) for m in items]
counts = [F.count(F.col(m)).alias(m) for m in items]
df_reshaped = df.select(F.col("ID"), *cols)
                .groupBy("ID")
                .agg(*counts)
df_reshaped.show()

最新更新