Каков наилучший способ найти элемент в столбце массива в spark scala? - PullRequest
0 голосов
/ 24 апреля 2020

У меня есть столбец массива, в котором я нахожу текст из него и формирую фрейм данных. Какой из двух вариантов лучше? Опция 1

val texts = Seq("text1", "text2", "text3")
 val df = mainDf.select(col("*"))
      .withColumn("temptext", explode($"textCol"))
      .where($"temptext".isin(texts: _*))

И так как он добавил и дополнительный столбец "temptext" и увеличил дублирующиеся строки, взорвав

  val tempDf = df.drop("temptext").dropDuplicates("Root.Id")  // dropDuplicates does not work since I have passed nested field

против

Вариант 2

val df = mainDf.select(col("*"))
  .where(array_contains($"textCol", "text1") ||
      array_contains($"textCol", "text2") ||
      array_contains($"textCol", "text3"))

На самом деле я хотел сделать универсальный c API, если I go с опцией 2

, то проблема в том, что для каждого нового текста мне нужно добавить array_contains ($ "textCol", "text4") и каждый раз создавать новый API

, а в варианте 1 он создает повторяющиеся строки, так как я разбиваю массив и также требую отбросить временный столбец

1 Ответ

0 голосов
/ 24 апреля 2020

Используйте arrays_overlap (или) array_intersect функций для передачи array(<strings>) вместо array_contains.

Example: 1.filter based on texts variable:

val df=Seq((Seq("text1")),(Seq("text4","text1")),(Seq("text5"))).
toDF("textCol")

df.show()
//+--------------+
//|       textCol|
//+--------------+
//|       [text1]|
//|[text4, text1]|
//|       [text5]|
//+--------------+

val texts = Array("text1","text2","text3")

//using arrays_overlap    
df.filter(arrays_overlap(col("textcol"),lit(texts))).show(false)
//+--------------+
//|textCol       |
//+--------------+
//|[text1]       |
//|[text4, text1]|
//+--------------+

//using arrays_intersect    
df.filter(size(array_intersect(col("textcol"),lit(texts))) > 0).show(false)
//+--------------+
//|textCol       |
//+--------------+
//|[text1]       |
//|[text4, text1]|
//+--------------+

2.Adding texts variable to the dataframe:

val texts = "text1,text2,text3"

val df=Seq((Seq("text1")),(Seq("text4","text1")),(Seq("text5"))).
toDF("textCol").
withColumn("texts",split(lit(s"${texts}"),","))

df.show(false)
//+--------------+---------------------+
//|textCol       |texts                |
//+--------------+---------------------+
//|[text1]       |[text1, text2, text3]|
//|[text4, text1]|[text1, text2, text3]|
//|[text5]       |[text1, text2, text3]|
//+--------------+---------------------+

//using array_intersect
df.filter("""size(array_intersect(textcol,texts)) > 0""").show(false)
//+--------------+---------------------+
//|textCol       |texts                |
//+--------------+---------------------+
//|[text1]       |[text1, text2, text3]|
//|[text4, text1]|[text1, text2, text3]|
//+--------------+---------------------+

//using arrays_overlap
df.filter("""arrays_overlap(textcol,texts)""").show(false)
+--------------+---------------------+
|textCol       |texts                |
+--------------+---------------------+
|[text1]       |[text1, text2, text3]|
|[text4, text1]|[text1, text2, text3]|
+--------------+---------------------+
...