Dataframe Spark SQL:当groupBy()中的另一列为max value时,获取该列的值。agg()
我有一个如下所示的数据帧:Dataframe Spark SQL:当groupBy()中的另一列为max value时,获取该列的值。agg(),dataframe,apache-spark,apache-spark-sql,Dataframe,Apache Spark,Apache Spark Sql,我有一个如下所示的数据帧: root |-- value: int (nullable = true) |-- date: date (nullable = true) val result = df .filter(df("date")>= somedate && df("date")<= some other date) .groupBy(valueFromColumn1) .agg( max(date), min(valueFromColu
root
|-- value: int (nullable = true)
|-- date: date (nullable = true)
val result = df
.filter(df("date")>= somedate && df("date")<= some other date)
.groupBy(valueFromColumn1)
.agg(
max(date),
min(valueFromColumn2),
Here I want to put valueFromColumn4 where date is max after the filter
)
我想返回value,其中value是数据帧中的最新日期。
如果我需要创建groupBy和agg,这个问题会改变吗?
我的实际问题如下所示:
root
|-- value: int (nullable = true)
|-- date: date (nullable = true)
val result = df
.filter(df("date")>= somedate && df("date")<= some other date)
.groupBy(valueFromColumn1)
.agg(
max(date),
min(valueFromColumn2),
Here I want to put valueFromColumn4 where date is max after the filter
)
输出sameple filter为date>=2006,date解决方案是使用结构将值和日期绑定在一起。它看起来是这样的:
root
|-- value: int (nullable = true)
|-- date: date (nullable = true)
val result = df
.filter(df("date")>= somedate && df("date")<= some other date)
.groupBy(valueFromColumn1)
.agg(
max(date),
min(valueFromColumn2),
Here I want to put valueFromColumn4 where date is max after the filter
)
val结果=df
.filterdfdate>=somedate&&dfdate您可以将groupBy与结构一起使用:
或带有窗口:
您要执行的操作是在列1上分组的一组数据中排序。这是的完美用例,它对一组记录执行计算 在这里,我们可以对第1列上的窗口进行分区,并从每个这样的窗口中选择最大日期。让我们将windowedPartition定义为:
val windowedPartition = Window.partitionBy("col1").orderBy(col("date").desc)
然后我们可以在数据集上应用这个窗口函数来选择排名最高的行。我没有在下面的代码中添加过滤逻辑,因为我认为这不会带来任何复杂性,也不会影响解决方案
工作代码:
scala> import org.apache.spark.sql.expressions.Window
import org.apache.spark.sql.expressions.Window
scala> val data = Seq(("a" , 1, 2006, 5), ("a", 5, 2018, 2), ("a", 3, 2000, 3), ("b", 13, 2007, 4)).toDF("col1", "col2", "date", "col4")
data: org.apache.spark.sql.DataFrame = [col1: string, col2: int ... 2 more fields]
scala> data.show
+----+----+----+----+
|col1|col2|date|col4|
+----+----+----+----+
| a| 1|2006| 5|
| a| 5|2018| 2|
| a| 3|2000| 3|
| b| 13|2007| 4|
+----+----+----+----+
scala> val windowedPartition = Window.partitionBy("col1").orderBy(col("date").desc)
windowedPartition: org.apache.spark.sql.expressions.WindowSpec = org.apache.spark.sql.expressions.WindowSpec@39613474
scala> data.withColumn("row_number", row_number().over(windowedPartition)).show
+----+----+----+----+----------+
|col1|col2|date|col4|row_number|
+----+----+----+----+----------+
| b| 13|2007| 4| 1|
| a| 5|2018| 2| 1|
| a| 1|2006| 5| 2|
| a| 3|2000| 3| 3|
+----+----+----+----+----------+
scala> data.withColumn("row_number", row_number().over(windowedPartition)).where(col("row_number") === 1).show
+----+----+----+----+----------+
|col1|col2|date|col4|row_number|
+----+----+----+----+----------+
| b| 13|2007| 4| 1|
| a| 5|2018| 2| 1|
+----+----+----+----+----------+
scala> data.withColumn("row_number", row_number().over(windowedPartition)).where(col("row_number") === 1).drop(col("row_number")).show
+----+----+----+----+
|col1|col2|date|col4|
+----+----+----+----+
| b| 13|2007| 4|
| a| 5|2018| 2|
+----+----+----+----+
我相信这将是一个比struct更具可扩展性的解决方案,因为如果列的数量增加,我们可能也必须在struct中添加这些列,在这个解决方案中,这种情况将得到解决
但有一个问题:
在o/p中,col2中的值应为5,因为col1=A对吗?col2的值是如何变为1的?您能添加一些预期的输入和输出示例吗?添加了示例,希望对您有所帮助。谢谢。