Метод максимального поиска в нескольких столбцах и объединение результата в одном столбце с помощью Spark

#scala #apache-spark #apache-spark-dataset

#scala #apache-spark #apache-spark-dataset

Вопрос:

У меня есть следующий набор данных :

  ---- ----- -------- ----- -------- 
|  id|date1|address1|date2|address2|
 ---- ----- -------- ----- -------- 
|   1| 2019|   Paris| 2018|  Madrid|
|   2| 2020|New York| 2002|  Geneva|
|   3| 1998|  London| 2005|   Tokyo|
|   4| 2005|  Sydney| 2013|  Berlin|
 ---- ----- ------- ------ -------- 
 

Я пытаюсь получить самую последнюю дату и соответствующий адрес каждого id из двух других столбцов. Желаемый результат :

  ---- ----- -------- ----- -------- -------- ----------- 
|  id|date1|address1|date2|address2|date_max|address_max|
 ---- ----- -------- ----- -------- -------- ----------- 
|   1| 2019|   Paris| 2018|  Madrid|    2019|      Paris|
|   2| 2020|New York| 2002|  Geneva|    2020|   New York| 
|   3| 1998|  London| 2005|   Tokyo|    2005|      Tokyo|
|   4| 2005|  Sydney| 2013|  Berlin|    2013|     Berlin|
 ---- ----- ------- ------ -------- -------- ----------- 
 

Есть идеи, как сделать это очень эффективным способом?

Ответ №1:

Вы можете сделать CASE WHEN , чтобы выбрать более свежую дату / адрес:

 import org.apache.spark.sql.functions._

val date_max = when(col("date1") > col("date2"), col("date1")).otherwise(col("date2")).alias("date_max")
val address_max = when(col("date1") > col("date2"), col("address1")).otherwise(col("address2")).alias("address_max")

df = df.select("*", date_max, address_max)
 

Если вы хотите более масштабируемый вариант со многими столбцами:

 val df2 = df.withColumn(
    "all_date",
    array(df.columns.filter(_.contains("date")).map(col): _*)
).withColumn(
    "all_address",
    array(df.columns.filter(_.contains("address")).map(col): _*)
).withColumn(
    "date_max",
    array_max($"all_date")
).withColumn(
    "address_max",
    element_at($"all_address",
        (array_position($"all_date", array_max($"all_date"))).cast("int")
    )
).drop("all_date", "all_address")

df2.show
 --- ----- -------- ----- -------- ------- ---------- 
| id|date1|address1|date2|address2|datemax|addressmax|
 --- ----- -------- ----- -------- ------- ---------- 
|  1| 2019|   Paris| 2018|  Madrid|   2019|     Paris|
|  2| 2020| NewYork| 2002|  Geneva|   2020|   NewYork|
|  3| 1998|  London| 2005|   Tokyo|   2005|     Tokyo|
|  4| 2005|  Sydney| 2013|  Berlin|   2013|    Berlin|
 --- ----- -------- ----- -------- ------- ---------- 

 

Комментарии:

1. В моем случае у меня есть около пятнадцати столбцов даты и адреса для сравнения. Как я могу использовать CASE WHEN функцию с таким количеством столбцов?

2. @Mamaf Я обновил свой ответ для многих столбцов