СКАЛА: Могу ли я иметь условие внутри где или фильтра? - PullRequest
3 голосов
/ 04 июля 2019

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

val testerList = List("a","k")

Кадр данных должен быть отфильтрован, чтобы включать только записи с указанными буквами всписок.Это очень просто:

val resultDF = df.where($"column".isin(testerList:_*)))

Таким образом, проблема в том, что список передается этой функции в качестве параметра, и это может быть пустой список, какую ситуацию можно решить подобным образом (определяется resultDFздесь как пустой фрейм данных):

if (!(testerList.isEmpty)) {
 resultDF = df.where(some other stuff has to be filtered away)
                  .where($"column".isin(testerList:_*)))
} else {
  resultDF = df.where(some other stuff has to be filtered away)
}

Есть ли способ сделать это более простым способом, что-то вроде этого:

val resultDF = df.where(some other stuff has to be filtered away)
                      .where((!(testerList.isEmpty)) && $"column".isin(testerList:_*)))

Этот выдает ошибку, хотя:

 error: type mismatch;
 found   : org.apache.spark.sql.Column
 required: Boolean
                                    .where( (!(testerList.isEmpty)) && (($"agent_account_homepage").isin(testerList:_*)))
                                                                                                        ^

Итак, большое спасибо за любые идеи для решения !!:)

Ответы [ 3 ]

3 голосов
/ 04 июля 2019

Как насчет этого?

val filtered1 = df.where(some other stuff has to be filtered away)
val resultDF = if (testerList.isEmpty) 
  filtered1 
else 
  filtered1.where($"column".isin(testerList:_*))

Или, если вы не хотите, чтобы filtered1 был доступен ниже и, возможно, использовался непреднамеренно, его можно объявить внутри блока, инициализирующего resultDF:

val resultDF = {
  val filtered1 = df.where(some other stuff has to be filtered away)
  if (testerList.isEmpty) filtered1 else filtered1.where($"column".isin(testerList:_*))
}

или если вы измените заказ

val resultDF = (if (testerList.isEmpty) 
  df
else 
  df.where($"column".isin(testerList:_*))
).where(some other stuff has to be filtered away)
2 голосов
/ 04 июля 2019

По существу, то, что Spark ожидает получить в where, является простым объектом Column.Это означает, что вы можете извлечь всю свою сложную логику , где , чтобы отделить функцию:

def testerFilter(testerList: List[String]): Column = testerList match {
   //of course, you have to replace ??? with real conditions
   //just apend them by joining with "and"
    case Nil => $"column".isNotNull and ??? 
    case tl => $"column".isin(tl: _*) and ???
}

И затем вы просто используете ее как:

df.where(testerFilter(testerList))
1 голос
/ 04 июля 2019

Решение, которое я использую сейчас, использует SQL-код внутри предложения where:

var testerList = s""""""
var cond = testerList.isEmpty().toString
testerList = if (cond == "true") "''" else testerList

val resultDF= df.where(some other stuff has to be filtered away)
                .where("('"+cond+"' = 'true') or (agent_account_homepage in ("+testerList+"))")

Что вы думаете?

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