Pyspark上的逻辑调节 - 与何时聚合

时间:2018-03-14 14:18:53

标签: apache-spark pyspark

有人可以向我解释为什么这两个条件产生不同的输出(甚至不同的count())?

FIRST:

(df
 .where(cond1)
 .where((cond2) | (cond3))
 .groupBy('id')
 .agg(F.avg(F.column('col1')).alias('name'),
      F.avg(F.column('col2')).alias('name'))
).count()

第二

(df
 .groupBy('id')
 .agg(F.avg(F.when(((cond2) | (cond3))) & (cond1),
                   F.column('col1'))).alias('name'),
      F.avg(F.when(((cond2) | (cond3)) & (cond1),
                   F.column('col2'))).alias('name'))
).count()

2 个答案:

答案 0 :(得分:0)

我只是想通了。 when()在找不到匹配时返回None,但None仍然是返回,这意味着聚合会考虑所有值。当与由同一列分组并且没有条件聚合的简单df进行比较时,结果是相同的。

另一方面,where()过滤DataFrame,因此聚合仅应用于DataFrame的过滤版本,因此结果数量较少

答案 1 :(得分:0)

在不知道条件是什么的情况下,我的理解是它们是不同的过程:在第一种情况下,您首先过滤行,您需要处理,按ID分组并获取过滤的平均值数据,结果让我们说x行。在第二种情况下,您首先按ID分组,不进行行过滤,并告诉spark添加名为“name”的列,该列保存条件平均值到分组的df。您没有有条件地过滤行,因此您现在有x +更多行(取决于您的条件)

(df
 .where(cond1)              # remove rows by applying cond1
 .where((cond2) | (cond3))  # remove rows by applying cond2, 3
 .groupBy('id')             # group *remaining* rows by id
 .agg(F.avg(F.column('col1')).alias('name'), # then get the average
      F.avg(F.column('col2')).alias('name'))
).count()

可是:

(df
 .groupBy('id')  # group initial data by id
 .agg(F.avg(F.when(((cond2) | (cond3))) & (cond1), # add a column to the grouped data that computes average conditionally
                   F.column('col1'))).alias('name'),
      F.avg(F.when(((cond2) | (cond3)) & (cond1),
                   F.column('col2'))).alias('name'))
).count()

# the agg does not change the number of the rows.

希望这会有所帮助(我认为你已经弄明白了:))。祝你好运!