Проверьте, что в строке Spark Dataframe есть ЛЮБОЙ столбец, соответствующий условию, и остановитесь, когда первый такой столбец найден - PullRequest
0 голосов
/ 25 февраля 2019

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

import org.apache.spark.sql.types.StructType

val df = sc.parallelize(Seq(
   ("r1", 1, 1),
   ("r2", 6, 4),
   ("r3", 4, 1),
   ("r4", 1, 2)
   )).toDF("ID", "a", "b")

val ones = df.schema.map(c => c.name).drop(1).map(x => when(col(x) === 1, 1).otherwise(0)).reduce(_ + _)

df.withColumn("ones", ones).where($"ones" === 0).show

Недостатком здесь является то, что в идеале он должен останавливаться при первом таком условиивстретилТ.е. найден первый столбец.ОК, мы все это знаем.

Но я не могу найти элегантный метод для достижения этого без предположительно использования UDF или очень специфической логики.Карта обработает все столбцы.

Можно ли поэтому использовать складку (слева), которая может закончиться, когда возможно первое обнаружение?Или какой-то другой подход?Может быть недосмотр.

1 Ответ

0 голосов
/ 25 февраля 2019

Моей первой идеей было использование логических выражений и надежды на короткое замыкание, но похоже, что искра этого не делает:

df
  .withColumn("ones", df.columns.tail.map(x => when(col(x) === 1, true).otherwise(false)).reduceLeft(_ or _))
  .where(!$"ones")
  .show()

Но я не уверен, поддерживает ли искра короткое замыкание,Я думаю, что нет (https://issues.apache.org/jira/browse/SPARK-18712)

Так что в качестве альтернативы вы можете применить пользовательскую функцию к своим строкам, используя lazy exist для Seq в scala:

df
  .map{r => (r.getString(0),r.toSeq.tail.exists(c => c.asInstanceOf[Int]==1))}
  .toDF("ID","ones")
  .show()

Этот подход аналогиченUDF, так что не уверен, что это то, что ты принимаешь.

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