Как получить набор строк, который содержит нулевые значения из фрейма данных в scala, используя фильтр - PullRequest
3 голосов
/ 18 июня 2020

Я новичок в Spark и у меня есть вопрос о фильтрации фрейма данных на основе нулевого условия. Я просмотрел много ответов, в которых есть такие решения, как

df.filter(($"col2".isNotNULL) || ($"col2" !== "NULL")  || ($"col2" !== "null")  || ($"col2".trim !== "NULL"))

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

например: Input DataFrame:

+----+----+---------+---------+
|name|  id|    email|  company|
+----+----+---------+---------+
|  n1|null|n1@c1.com|[c1,1,d1]|
|  n2|   2|null     |[c1,1,d1]|
|  n3|   3|n3@c1.com| null    |
|  n4|   4|n4@c2.com|[c2,2,d2]|
|  n6|   6|n6@c2.com|[c2,2,d2]|

Output:

+----+----+---------+---------+
|name|  id|    email|  company|
+----+----+---------+---------+
|  n1|null|n1@c1.com|[c1,1,d1]|
|  n2|   2|null     |[c1,1,d1]|
|  n3|   3|n3@c1.com| null    |

Заранее благодарю

Ответы [ 3 ]

1 голос
/ 18 июня 2020

Для работы с нулевыми значениями и фреймами данных у Spark есть несколько полезных функций.

Я покажу несколько примеров фреймов данных с различным количеством столбцов.

      val schema = StructType(List(StructField("id", IntegerType, true), StructField("obj",DoubleType, true)))
      val schema1 = StructType(List(StructField("id", IntegerType, true), StructField("obj",StringType, true), StructField("obj",IntegerType, true)))

      val t1 = sc.parallelize(Seq((1,null),(1,1.0),(8,3.0),(2,null),(3,1.4),(3,2.5),(null,3.7))).map(t => Row(t._1,t._2))
      val t2 = sc.parallelize(Seq((1,"A",null),(2,"B",null),(3,"C",36),(null,"D",15),(5,"E",25),(6,null,7),(7,"G",null))).map(t => Row(t._1,t._2,t._3))
      val tt1 = spark.createDataFrame(t1, schema)
      val tt2 = spark.createDataFrame(t2, schema1)

      tt1.show()
      tt2.show()

      // To clean all rows with null values
      val dfWithoutNull = tt1.na.drop()
      dfWithoutNull.show()

      val df2WithoutNull = tt2.na.drop()
      df2WithoutNull.show()

      // To fill null values with another value
      val df1 = tt1.na.fill(-1)
      df1.show()

      // to get new dataframes with the null values rows
      val nullValues = tt1.filter(row => row.anyNull == true)
      nullValues.show()

      val nullValues2 = tt2.filter(row => row.anyNull == true)
      nullValues2.show()

вывод

// input dataframes
+----+----+
|  id| obj|
+----+----+
|   1|null|
|   1| 1.0|
|   8| 3.0|
|   2|null|
|   3| 1.4|
|   3| 2.5|
|null| 3.7|
+----+----+

+----+----+----+
|  id| obj| obj|
+----+----+----+
|   1|   A|null|
|   2|   B|null|
|   3|   C|  36|
|null|   D|  15|
|   5|   E|  25|
|   6|null|   7|
|   7|   G|null|
+----+----+----+

// Dataframes without null values
+---+---+
| id|obj|
+---+---+
|  1|1.0|
|  8|3.0|
|  3|1.4|
|  3|2.5|
+---+---+

+---+---+---+
| id|obj|obj|
+---+---+---+
|  3|  C| 36|
|  5|  E| 25|
+---+---+---+

// Dataframe with null values replaced
+---+----+
| id| obj|
+---+----+
|  1|-1.0|
|  1| 1.0|
|  8| 3.0|
|  2|-1.0|
|  3| 1.4|
|  3| 2.5|
| -1| 3.7|
+---+----+

// Dataframes which the rows have at least one null value
+----+----+
|  id| obj|
+----+----+
|   1|null|
|   2|null|
|null| 3.7|
+----+----+

+----+----+----+
|  id| obj| obj|
+----+----+----+
|   1|   A|null|
|   2|   B|null|
|null|   D|  15|
|   6|null|   7|
|   7|   G|null|
+----+----+----+
1 голос
/ 18 июня 2020

Большое спасибо за ваши ответы. Я пробовал ниже logi c, и у меня это сработало.

var arrayColumn = df.columns;
        val filterString = String.format(" %1$s is null or %1$s == '' "+ arrayColumn(0));
        val x = new StringBuilder(filterString);
        for(i <- 1 until arrayColumn.length){
          if (x.toString() != ""){
            x ++= String.format("or %1$s is null or %1$s == '' ", arrayColumn(i))
          }
        }
        val dfWithNullRows =  df.filter(x.toString());
1 голос
/ 18 июня 2020

Попробуйте это -


    val df1 = spark.sql("select col1, col2 from values (null, 1), (2, null), (null, null), (1,2) T(col1, col2)")
    /**
      * +----+----+
      * |col1|col2|
      * +----+----+
      * |null|1   |
      * |2   |null|
      * |null|null|
      * |1   |2   |
      * +----+----+
      */

    df1.show(false)
    df1.filter(df1.columns.map(col(_).isNull).reduce(_ || _)).show(false)

    /**
      * +----+----+
      * |col1|col2|
      * +----+----+
      * |null|1   |
      * |2   |null|
      * |null|null|
      * +----+----+
      */
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...