pysparksql从组中获取所有最高值并评估是否存在重复

oyjwcjzk  于 2021-07-12  发布在  Spark
关注(0)|答案(1)|浏览(252)

考虑以下Dataframe:

+----------+------+--+
|    person| style| n|
+----------+------+--+
|        P1|     A| 1|
|        P2|     A| 1|
|        P2|     B| 2|
|        P3|     A| 1|
|        P3|     B| 2|
|        P3|     C| 2|
|        P4|     A| 2|
|        P4|     B| 2|
+----------+------+--+

目标是确定每个人喜欢的风格。然而,偏好有着复杂的规则!
如果一个人有一个单一的风格(例如。 P1 )不管观察的次数多少,这种风格都是他们的首选 n .
如果一个人有两种或两种以上的风格,其中一种显然是最好的 n (例如。 P2 风格 B )那就是偏好。
现在越来越难了。如果一个人有3种或3种以上的风格,其中至少有2种 n 都是最高的值并且是相同的,那么所有的样式都是最高的 n 被认为是偏好(例如。 P3 样式 B 以及 C )
如果一个人有两种或两种以上的风格 n 是相同的,没有设置首选项(例如。 P4 ). 注意,如果 P3 还有一个 n 为时尚 A (为了成功) 2 )那么它也属于这一类。
在尝试spark之前,我只想 GROUP 以及 ORDERperson 会重复这些结果,嗅探 max(n) 一般来说是通过编程来处理的。但我对spark还很陌生,我知道应该避免迭代和收集之类的东西。我想我的目标输出帧是

+----------+------+--+
|    person| style| n|
+----------+------+--+
|        P1|     A| 1|
|        P2|     B| 2|
|        P3|     B| 2|
|        P3|     C| 2|
+----------+------+--+

有几个很好的例子可以在一个列中找到最大值 GROUP BY 但这不符合上述第3条或第4条的规定。
我猜是某种自我连接 (count(max(n)) <> count(*)) or count(max(n)) = 1 但我不擅长sql。
不是为了让这成为一个竞赛,而是作为一个比较,在mongodb中,我会为每个人将样式和计数放入一个数组中,然后使用 $reduce 遍历数组并应用逻辑 n 在每个样式中都是相同的,然后用表示状态的代码“标记”文档(而不是数组)。

wmomyfyw

wmomyfyw1#

您可以使用条件4标记行,并在执行常规操作后删除它们 row_number 诡计(实际上 rank 这里,因为你想根据条件3保持联系):

from pyspark.sql import functions as F, Window

df2 = df.withColumn(
    'cond', 
    (F.count('*').over(Window.partitionBy('person')) > 1) & 
    (F.min('n').over(Window.partitionBy('person')) == 
     F.max('n').over(Window.partitionBy('person'))
    )
).withColumn(
    'rn', 
    F.rank().over(Window.partitionBy('person').orderBy(F.desc('n')))
).filter('rn = 1 and not cond').drop('cond', 'rn')

df2.show()
+------+-----+---+
|person|style|  n|
+------+-----+---+
|    P2|    B|  2|
|    P3|    B|  2|
|    P3|    C|  2|
|    P1|    A|  1|
+------+-----+---+

相关问题