<blockquote>
<p>I understand, each category requires a full scan of the DataFrame. </p>
</blockquote>
<p>不,它不是。数据帧聚合是使用类似于<code>aggregateByKey</code>的逻辑执行的。请参阅<a href="https://stackoverflow.com/q/32902982/1560062">DataFrame groupBy behaviour/optimization</a>较慢的部分是<code>join</code>,它需要排序/洗牌。但它仍然不需要每个组扫描。在</p>
<p>如果这是一个确切的代码,那么使用它是很慢的,因为您没有提供连接表达式。因为它只是执行笛卡尔积。因此,它不仅效率低下,而且是不正确的。你想要这样的东西:</p>
<pre><code>from pyspark.sql.functions import col
means = df.groupBy("Category").mean("Values").alias("means")
df.alias("df").join(means, col("df.Category") == col("means.Category"))
</code></pre>
<blockquote>
<p>I think (but have not verified) that I can speed this up a great deal if I collect the result of the group-by/mean into a dictionary, and then use that dictionary in a UDF</p>
</blockquote>
<p>这是可能的,尽管性能会因具体情况而有所不同。使用Python udf的一个问题是它必须在Python之间来回移动数据。不过,这绝对值得一试。但是,您应该考虑为<code>nameToMean</code>使用广播变量。在</p>
<blockquote>
<p>Is there an idiomatic way to express this type of operation without sacrificing performance?</p>
</blockquote>
<p>在PySpark 1.6中,您可以使用<code>broadcast</code>函数:</p>
^{pr2}$
<p>但在<;=1.5中不可用。在</p>