Я хочу добавить условный столбец Flag
в фрейм данных A. Когда следующие два условия выполнены, добавьте 1 к Flag
, иначе 0:
num
из фрейма данных A находится между numStart
и numEnd
из фрейма данных B.
Если приведенное выше условие выполняется, проверьте, равно ли include
1.
DataFrame A (это очень большой фрейм данных, содержащий миллионы строк):
+----+------+-----+------------------------+
|num |food |price|timestamp |
+----+------+-----+------------------------+
|1275|tomato|1.99 |2018-07-21T00:00:00.683Z|
|145 |carrot|0.45 |2018-07-21T00:00:03.346Z|
|2678|apple |0.99 |2018-07-21T01:00:05.731Z|
|6578|banana|1.29 |2018-07-20T01:11:59.957Z|
|1001|taco |2.59 |2018-07-21T01:00:07.961Z|
+----+------+-----+------------------------+
DataFrame B (это очень маленький DF, содержащий всего 100 строк):
+----------+-----------+-------+
|numStart |numEnd |include|
+----------+-----------+-------+
|0 |200 |1 |
|250 |1050 |0 |
|2000 |3000 |1 |
|10001 |15001 |1 |
+----------+-----------+-------+
Ожидаемый результат:
+----+------+-----+------------------------+----------+
|num |food |price|timestamp |Flag |
+----+------+-----+------------------------+----------+
|1275|tomato|1.99 |2018-07-21T00:00:00.683Z|0 |
|145 |carrot|0.45 |2018-07-21T00:00:03.346Z|1 |
|2678|apple |0.99 |2018-07-21T01:00:05.731Z|1 |
|6578|banana|1.29 |2018-07-20T01:11:59.957Z|0 |
|1001|taco |2.59 |2018-07-21T01:00:07.961Z|0 |
+----+------+-----+------------------------+----------+
Соедините два фрейма данных вместе по первому условию, сохранив все строки в фрейме данных A (т. е. с левым соединением, см. код ниже). После объединения столбец include
можно переименовать в Flag
, а любые значения NaN внутри него установить равными 0. Два дополнительных столбца, numStart
и numEnd
, удаляются.
Таким образом, код можно записать следующим образом:
A.join(B, $"num" >= $"numStart" && $"num" <= $"numEnd", "left")
.withColumnRenamed("include", "Flag")
.drop("numStart", "numEnd")
.na.fill(Map("Flag" -> 0))
Вы можете выполнить левое соединение dfB
с dfA
на основе условия, которое вы описали в (i), затем построить столбец Flag
, используя withColumn
и функцию coalesce
, чтобы «по умолчанию» было равно 0:
include
значение совпадающей dfB
записи.include=null
, и по вашему требованию такие записи должны получить Flag=0
, поэтому мы используем coalesce
, который в случае нулевого значения возвращает значение по умолчанию с литералом lit(0)
Наконец, избавьтесь от столбцов dfB
, которые вас не интересуют:
import org.apache.spark.sql.functions._
import spark.implicits._ // assuming "spark" is your SparkSession
dfA.join(dfB, $"num".between($"numStart", $"numEnd"), "left")
.withColumn("Flag", coalesce($"include", lit(0)))
.drop(dfB.columns: _*)
.show()
// +----+------+-----+--------------------+----+
// | num| food|price| timestamp|Flag|
// +----+------+-----+--------------------+----+
// |1275|tomato| 1.99|2018-07-21T00:00:...| 0|
// | 145|carrot| 0.45|2018-07-21T00:00:...| 1|
// |2678| apple| 0.99|2018-07-21T01:00:...| 1|
// |6578|banana| 1.29|2018-07-20T01:11:...| 0|
// |1001| taco| 2.59|2018-07-21T01:00:...| 0|
// +----+------+-----+--------------------+----+
Спасибо за ваш ответ, но я получаю сообщение об ошибке «Не удается разрешить объединение символов» и «Не удается разрешить символ горит». Также, если я могу спросить, каково обоснование объединения в столбце «включить»?
Какую версию Spark вы используете? И включили ли вы первый оператор импорта (импорт functions._
) в свой код? Вот откуда должна появиться функция lit
. Что касается использования coalesce
: добавлено объяснение в ответ.
что ты уже испробовал? Вы пытались присоединиться к кадрам данных на основе условия, описанного в пункте (i)?