问题描述
来自sql开发背景,目前正在学习pyspark / python,我对使用python查询数据/链接方法有些困惑。@H_404_1@
例如以下查询(摘自“ Learning Spark 2nd Edition”):@H_404_1@
fire_ts_df.
select("CallType")
.where(col("CallType").isNotNull())
.groupBy("CallType")
.count()
.orderBy("count",ascending=False)
.show(n=10,truncate=False)
将执行得很好。@H_404_1@
我不明白的是,如果我编写了如下代码:(将对“ count()”的调用提高了)@H_404_1@
fire_ts_df.
select("CallType")
.count()
.where(col("CallType").isNotNull())
.groupBy("CallType")
.orderBy("count",truncate=False)
这行不通。 问题是我不想记住订单,但我想了解它。我觉得这与Python / Pyspark中正确的方法链接有关,但是我不确定如何证明它的合理性。换句话说,在这种情况下,应该使用(。)调用和链接多个方法,正确的顺序是什么,有什么特定的规则可遵循吗?@H_404_1@
非常感谢@H_404_1@
解决方法
这里要注意的重要一点是,链接方法不一定会随机出现。这些方法调用所代表的操作不是从左到右平坦地应用于数据的一些关联转换。
每个方法调用都可以编写为单独的语句,其中每个语句都会生成一个结果,该结果将输入下一个操作,依此类推,直到结果为止。
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)
如您所见,排序是有意义的,因为操作的连续性与其各自的输出一致。
链式调用使所谓的流利的API最小化了冗长性。但这并不能消除以下事实:链接方法必须适用于前一个调用的输出类型(实际上,下一个操作旨在应用于前一个调用的输出所产生的值)。>