我有一个带有
A
字段的 PySpark Dataframe,几个依赖于 B
(A
) 和我想要为每个 A 聚合的 A->B
字段的 C
字段。例如:
A | B | C
----------
A | 1 | 6
A | 1 | 7
B | 2 | 8
B | 2 | 4
我希望按
A
进行分组,呈现任何 B
并在 SUM
上运行聚合(假设是 C
)。
预期结果是:
A | B | C
----------
A | 1 | 13
B | 2 | 12
就 SQL 而言,我会这样做:
SELECT A, COALESCE(B) as B, SUM(C) as C
FROM T
GROUP BY A
PySpark 的方法是什么?
我可以将 A 和 B 分组在一起,或者为每个 A 选择
MIN(B)
,例如:
df.groupBy('A').agg(F.min('B').alias('B'),F.sum('C').alias('C'))
或
df.groupBy(['A','B']).agg(F.sum('C').alias('C'))
但这似乎效率低下。 PySpark 中有类似 SQL
coalesce
的东西吗?
谢谢
您只需要使用
first
即可:
from pyspark.sql.functions import first, sum, col
from pyspark.sql import Row
array = [Row(A="A", B=1, C=6),
Row(A="A", B=1, C=7),
Row(A="B", B=2, C=8),
Row(A="B", B=2, C=4)]
df = sqlContext.createDataFrame(sc.parallelize(array))
results = df.groupBy(col("A")).agg(first(col("B")).alias("B"), sum(col("C")).alias("C"))
现在让我们检查结果:
results.show()
# +---+---+---+
# | A| B| C|
# +---+---+---+
# | B| 2| 12|
# | A| 1| 13|
# +---+---+---+
来自评论:
这里的
在计算上等同于first
吗?any
groupBy
导致随机播放。因此,“非确定性”行为是可以预料的。
这在 first
的文档中得到证实:
聚合函数:返回组中的第一个值。 默认情况下,该函数返回它看到的第一个值。当ignoreNulls设置为true时,它将返回它看到的第一个非空值。如果所有值都为 null,则返回 null。 注意:: 该函数是不确定的,因为它的结果取决于行的顺序,而行的顺序在洗牌后可能是不确定的。
是的所以
,在计算上是相同的,如果您需要确定性行为,这就是您需要使用排序的原因之一。 我希望这有帮助!
您可以使用聚合函数
any_value
来完成此操作。
通过这个新函数重用@eliasah的答案:from pyspark.sql.functions import any_value, sum, col
from pyspark.sql import Row
array = [Row(A="A", B=1, C=6),
Row(A="A", B=1, C=7),
Row(A="B", B=2, C=8),
Row(A="B", B=2, C=4)]
df = sqlContext.createDataFrame(sc.parallelize(array))
results = df.groupBy(col("A")).agg(any_value(col("B")).alias("B"), sum(col("C")).alias("C"))