Pyspark交叉表枢轴挑战/问题
不幸的是,我找不到解决问题的办法。它与pivot和crosstab有关,但我无法用这些函数解决它。 我有种感觉,我错过了一张中间的桌子,但不知何故,我无法想出一个解决办法 问题描述: 有客户的表格,表明他们从哪个类别购买了产品。如果客户从该类别购买了产品,则类别ID将显示在其姓名旁边 有4个类别1-4和3个客户A、B、CPyspark交叉表枢轴挑战/问题,pyspark,pivot,crosstab,Pyspark,Pivot,Crosstab,不幸的是,我找不到解决问题的办法。它与pivot和crosstab有关,但我无法用这些函数解决它。 我有种感觉,我错过了一张中间的桌子,但不知何故,我无法想出一个解决办法 问题描述: 有客户的表格,表明他们从哪个类别购买了产品。如果客户从该类别购买了产品,则类别ID将显示在其姓名旁边 有4个类别1-4和3个客户A、B、C +--------+----------+ |customer| category | +--------+----------+ | A| 1|
+--------+----------+
|customer| category |
+--------+----------+
| A| 1|
| A| 2|
| A| 3|
| B| 1|
| B| 4|
| C| 1|
| C| 3|
| C| 4|
+--------+----------+
该表具有独特的含义,即只有一个custmer和category组合
我想要的是一个按类别划分的交叉表,我可以轻松阅读,例如,从类别1购买的人中有多少人也从类别4购买
预期结果表:
+--------+---+---+---+---+
| | 1 | 2 | 3 | 4 |
+--------+---+---+---+---+
| 1| 3| 1| 2| 2|
| 2| 1| 1| 1| 0|
| 3| 2| 1| 2| 1|
| 4| 2| 0| 1| 1|
+--------+---+---+---+---+
阅读示例:
第1行第1列:购买产品1(A、B、C)的客户总数
第1行第2列:购买产品1和产品2的客户数量(A)
第1行第3列:购买产品1和产品3的客户数量(A、C)
等
如您所见,该表通过其对角线镜像
对如何创建所需的表有何建议
其他挑战:
如何将结果设置为%?
对于第一行,结果将为:| 100%| 33%| 66%| 66%|
非常感谢 您可以使用
customer
作为连接标准来连接输入数据本身。这将返回给定客户存在的所有类别组合。之后,您可以使用来获得结果
df2=df.WithColumnRename(“类别”、“cat1”)。加入(df.WithColumnRename(“类别”、“cat2”)、“客户”)\
.交叉表(“第1类”、“第2类”)\
.订购人(“cat1\U cat2”)
df2.show()
输出:
+---------+---+---+---+---+
|一类|二类|一|二|三|四|
+---------+---+---+---+---+
| 1| 3| 1| 2| 2|
| 2| 1| 1| 1| 0|
| 3| 2| 1| 2| 1|
| 4| 2| 0| 1| 2|
+---------+---+---+---+---+
要获得相对频率,可以对每行求和,然后将每个元素除以该和
df2.withColumn(“sum”,sum(df2[col]表示df2.columns中的col,如果col!=“cat1\u cat2”))\
.选择(“cat1_cat2”、*(F.round(df2[col]/F.col(“sum”),2.如果col!=“cat1_cat2”),则为df2.columns中的col选择别名(col))\
.show()
输出:
+---------+----+----+----+----+
|一类|二类|一|二|三|四|
+---------+----+----+----+----+
| 1|0.38|0.13|0.25|0.25|
| 2|0.33|0.33|0.33| 0.0|
| 3|0.33|0.17|0.33|0.17|
| 4| 0.4| 0.0| 0.2| 0.4|
+---------+----+----+----+----+
你好,沃纳,谢谢你的帮助。第一个解决方案非常有效!第二个需要修改,因为基础(100%)始终是对角线(1-1;2-2等)。因此,我通过以下方式对您的解决方案进行了改进:对每个类别的不同客户进行计数,并将其加入交叉表,并使用它来代替行的总和:df2=df2.join(df_max.withColumnRename('category'、'cat1_cat2')、'cat1_cat2'、'inner')cz3=df2.select(“cat1_cat2”、*(F.round(df2[col]/F.col(“total”),2)别名(col)对于df2.columns中的col,如果col!=“cat1\u cat2”)
Oh我忘了显示“df\u max”的来源:df\u max=df.groupBy('category').agg(F.countDistinct('customer').alias('total')