Как правильно фильтровать столбец с данными, разделенными запятой? - PullRequest
0 голосов
/ 17 февраля 2020

Допустим, у меня есть такой DataFrame.

+-----------+
|amount     |
+-----------+
|100,200,300|
|73         |
|56,89      |
+-----------+

Кроме того, у меня есть массив с числами: var array = Array(200, 73).

Я хочу отфильтровать этот DataFrame по массиву и взять такой результат:

+-----------+
|amount     |
+-----------+
|100,200,300|
|73         |
+-----------+

Я использовал такой код, но он не работает так, как я думал

df.filter(col("amount").isin(array: _*))

Мой следующий код возвращает такой результат:

+-----------+
|amount     |
+-----------+
|73         |
+-----------+

Что я не так сделал?

Ответы [ 4 ]

3 голосов
/ 17 февраля 2020

Если вы не можете использовать Spark 2.4, здесь есть другой способ использования функций array_contains и split.

Сначала разбейте столбец amount чтобы получить столбец массива:

val df2 = df.withColumn("amount_array", split($"amount", ","))

Затем отфильтруйте, используя это выражение фильтра:

val filterExpr = array.map(v => array_contains($"amount_array", v)).reduce(_ or _)

df2.filter(filterExpr).drop("amount_array").show()

//+-----------+
//|     amount|
//+-----------+
//|100,200,300|
//|         73|
//+-----------+
3 голосов
/ 17 февраля 2020

split столбец в массив строк, intersect с литеральным столбцом значений, которые необходимо отфильтровать, и затем проверить, больше ли размер результата, чем ноль:

val df = sc.parallelize(Seq("100,200,300", "73", "56,89")).toDF("amount")
// df: org.apache.spark.sql.DataFrame = [amount: string]

val array = Array("200", "73")
// array: Array[String] = Array(200, 73)

df.filter(size(array_intersect(split($"amount", ","), lit(array))) > 0).show
+-----------+
|     amount|
+-----------+
|100,200,300|
|         73|
+-----------+
1 голос
/ 17 февраля 2020

Метод isin , сравните точную версию левой строки с массивом значений в правой части. Проблема в вашем случае заключается в том, что он попытался сравнить строку «100,200,300» со строкой «200», очевидно, она не будет совпадать.

Один из способов решения этой проблемы - разбить столбец строки, разделенный запятой. и затем примените метод isin к разнесенному столбцу, он будет работать.

df.withColumn("exploded", explode(split(col("amount"), ",")))
.filter(col("exploded").isin(array: _*))
.drop(col("exploded"))
.show()
0 голосов
/ 17 февраля 2020

Если у вас Spark 2.4+, используйте функции массива, такие как array_intersect, в противном случае используйте UDF:

val containsStr = udf((data:String) => data.split(",").exists(array.contains))

df
  .where(containsStr($"amount"))
  .show()
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...