Как я могу принять условие фильтра наивысшего ранжирования, которое заканчивается сопоставлением в кадре данных? - PullRequest
0 голосов
/ 17 мая 2018

Формулировка моего вопроса может сбивать с толку, поэтому позвольте мне объяснить.Скажем, у меня есть массив строк.Они ранжируются в порядке наилучшего соответствия сценария.Таким образом, в индексе 0 мы хотим, чтобы это всегда существовало в столбце данных, но если этого не произойдет, индекс 1 будет следующим лучшим вариантом.Я написал эту логику вот так, но я не чувствую, что это самый эффективный способ сделать это.Есть ли другой способ сделать это лучше?

Наборы данных довольно малы, но я боюсь, что это не очень хорошо масштабируется.

val df = spark.createDataFrame(data)

val nameArray = Array[String]("Name", "Name%", "%Name%", "Person Name", "Person Name%", "%Person Name%")

nameArray.foreach(x => {
  val nameDf = df.where("text like '" + x + "'")

  if(nameDf.count() > 0){
    nameDf.show(1)
    break()
  }
})

1 Ответ

0 голосов
/ 17 мая 2018

Если значения располагаются в порядке в соответствии с предпочтением слева (наивысший приоритет) справа (наименьший приоритет), а шаблоны с более низким приоритетом уже охватывают шаблоны с более высоким приоритетом (это не похоже на случай в вашем примере), вы генерируете выражение какthis

import org.apache.spark.sql._

def matched(df: DataFrame, nameArray: Seq[String], c: String = "text") = {

  val matchIdx = nameArray.zipWithIndex.foldRight(lit(-1)){
    case ((s, i), acc) => when(col(c) like s, lit(i)).otherwise(acc)
  }

  df.select(max(matchIdx)).first match {
    case Row(-1)     => None  // No pattern matches all records
    case Row(i: Int) => Some(nameArray(i))
  }
}

Примеры использования:

matched(Seq("Some Name", "Name", "Name Surname").toDF("text"), Seq("Name", "Name%", "%Name%"))
// Option[String] = Some(%Name%)

У этого метода есть два преимущества:

  • Требуется только одно действие.
  • Сопоставление с образцом может быть короткозамкнутым.

Если предварительные условия не выполнены, вы можете

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

val unmatchedCount: Map[String, Long] = df.select(
  nameArray.map(s => count(when(not($"text" like s), 1)).alias(s)): _*
).first.getValuesMap[Long](nameArray)

В отличие от первого подхода, он будет проверять все шаблоны, но для этого требуется только одиндействие.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...