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

时间:2018-03-08 14:07:36

标签: apache-spark pyspark pivot spark-dataframe

假设我有一个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  |
+---+--------+-----+------+----+

有项目列,每列有一个项目。对于每个用户,每列上的数字是用户购买的项目数。

2 个答案:

答案 0 :(得分:2)

如果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'])

现在,您可以使用groupby和pivot操作来获得结果。

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|
+---+---+----+------+---+

请记住,在透视操作中,没有必要提供不同的值,但提供这些值会加快过程。

答案 1 :(得分: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()