来自 SQL 开发背景,目前正在学习 pyspark/python 我对使用 python 查询数据/链接方法有点困惑。
例如下面的查询(取自“Learning Spark 2nd Edition”):
fire_ts_df.
select("CallType")
.where(col("CallType").isNotNull())
.groupBy("CallType")
.count()
.orderBy("count", ascending=False)
.show(n=10, truncate=False)
会执行得很好。但我不明白的是,如果我写了这样的代码:(将调用移动到 'count()' 更高)
fire_ts_df.
select("CallType")
.count()
.where(col("CallType").isNotNull())
.groupBy("CallType")
.orderBy("count", ascending=False)
.show(n=10, truncate=False)
这行不通。问题是我不想记住订单,但我想了解它。我觉得这与 Python/Pyspark 中的正确方法链有关,但我不确定如何证明它的合理性。换句话说,在这种情况下,应该使用 (.) 调用和链接多个方法,正确的顺序是什么,是否有任何特定的规则要遵循?
非常感谢提前
最佳答案
这里要注意的重要一点是,链式方法不一定以随机顺序出现。这些方法调用所代表的操作不是从左到右直接应用于数据的一些关联变换。
每个方法调用都可以写成一个单独的语句,其中每个语句产生一个结果,作为下一个操作的输入,依此类推,直到结果。
fire_ts_df.
select("CallType") # selects column CallType into a 1-col DF
.where(col("CallType").isNotNull()) # Filters rows on the 1-column DF from select()
.groupBy("CallType") # Group filtered DF by the one column into a pyspark.sql.group.GroupedData object
.count() # Creates a new DF off the GroupedData with counts
.orderBy("count", ascending=False) # Sorts the aggregated DF, as a new DF
.show(n=10, truncate=False) # Prints the last DF
只是为了使用您的示例来解释为什么这不起作用,请调用 count()
在 pyspark.sql.group.GroupedData
创建一个带有聚合结果的新数据框。但是count()
调用 DataFrame
对象仅返回记录数,这意味着以下调用 .where(col("CallType").isNotNull())
, 是很长的,这根本没有意义。多头没有那种过滤方法。如上所述,您可以通过在单独的语句中重写代码来以不同的方式对其进行可视化:
call_type_df = fire_ts_df.select("CallType")
non_null_call_type = call_type_df.where(col("CallType").isNotNull())
groupings = non_null_call_type.groupBy("CallType")
counts_by_call_type_df = groupings.count()
ordered_counts = counts_by_call_type_df.orderBy("count", ascending=False)
ordered_counts.show(n=10, truncate=False)
如您所见,排序是有意义的,因为操作的连续性与其各自的输出一致。链式调用构成了所谓的 fluent API,它最大限度地减少了冗长。但这并没有消除一个事实,即链式方法必须适用于前一个调用的输出类型(事实上,下一个操作旨在应用于前一个调用产生的值)。
关于Python/Pyspark - 正确的方法链顺序规则,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/63998196/