【问题标题】:Spark: Add column to dataframe conditionallySpark:有条件地向数据框添加列
【发布时间】:2016-04-26 19:04:53
【问题描述】:

我正在尝试获取我的输入数据:

A    B       C
--------------
4    blah    2
2            3
56   foo     3

并根据B是否为空在末尾添加一列:

A    B       C     D
--------------------
4    blah    2     1
2            3     0
56   foo     3     1

我可以通过将输入数据框注册为临时表,然后键入 SQL 查询来轻松地做到这一点。

但我真的很想知道如何只使用 Scala 方法而不需要在 Scala 中输入 SQL 查询。

我已经尝试过.withColumn,但我不能让它做我想做的事。

【问题讨论】:

    标签: scala apache-spark apache-spark-sql spark-dataframe


    【解决方案1】:

    这样的事情怎么样?

    val newDF = df.filter($"B" === "").take(1) match {
      case Array() => df
      case _ => df.withColumn("D", $"B" === "")
    }
    

    使用take(1) 应该有一个最小的命中

    【讨论】:

      【解决方案2】:

      我的错,我错过了问题的一部分。

      最好、最干净的方法是使用UDF。 代码中的解释。

      // create some example data...BY DataFrame
      // note, third record has an empty string
      case class Stuff(a:String,b:Int)
      val d= sc.parallelize(Seq( ("a",1),("b",2),
           ("",3) ,("d",4)).map { x => Stuff(x._1,x._2)  }).toDF
      
      // now the good stuff.
      import org.apache.spark.sql.functions.udf
      // function that returns 0 is string empty 
      val func = udf( (s:String) => if(s.isEmpty) 0 else 1 )
      // create new dataframe with added column named "notempty"
      val r = d.select( $"a", $"b", func($"a").as("notempty") )
      
          scala> r.show
      +---+---+--------+
      |  a|  b|notempty|
      +---+---+--------+
      |  a|  1|    1111|
      |  b|  2|    1111|
      |   |  3|       0|
      |  d|  4|    1111|
      +---+---+--------+
      

      【讨论】:

      • 这里只有一个数据帧在起作用。您可能需要重新阅读问题
      【解决方案3】:

      尝试withColumn 与函数when 如下:

      val sqlContext = new SQLContext(sc)
      import sqlContext.implicits._ // for `toDF` and $""
      import org.apache.spark.sql.functions._ // for `when`
      
      val df = sc.parallelize(Seq((4, "blah", 2), (2, "", 3), (56, "foo", 3), (100, null, 5)))
          .toDF("A", "B", "C")
      
      val newDf = df.withColumn("D", when($"B".isNull or $"B" === "", 0).otherwise(1))
      

      newDf.show() 显示

      +---+----+---+---+
      |  A|   B|  C|  D|
      +---+----+---+---+
      |  4|blah|  2|  1|
      |  2|    |  3|  0|
      | 56| foo|  3|  1|
      |100|null|  5|  0|
      +---+----+---+---+
      

      我添加了(100, null, 5) 行来测试isNull 案例。

      我使用Spark 1.6.0 尝试了此代码,但正如when 代码中所评论的,它适用于1.4.0 之后的版本。

      【讨论】:

      • 这正是我想要的。我用whenotherwise 尝试了一些不同的东西,但我想我弄错了确切的格式。有点跑题了,但你知道 Spark 是如何处理 withColumn 的吗?就像,如果我要添加约 20 列,执行 20 .withColumn 并将其保留为数据框或将其映射到 RDD 并将它们全部添加到地图中然后转换回数据框以保存到镶木地板会更快吗?
      • 刚刚找到this。我认为 UDF 是我正在寻找的。​​span>
      • 为什么这不适用于 if? df.withColumn("D", if(df("B") == "") lit(0) else lit(1))
      • @SumitKumarGhosh df("B") 是一列。条件df("B") == "" 永远不应该为真,因为列与字符串不是同一种对象。此外,条件df("B") == "" 是一个全有或全无的条件。正如我怀疑你想要的那样,它不是逐行评估的。相比之下,when/otherwise 语法是正确的
      • 我们可以在申请时做'in'查询
      猜你喜欢
      • 1970-01-01
      • 2015-11-19
      • 1970-01-01
      • 1970-01-01
      • 2021-03-02
      • 2021-04-19
      • 1970-01-01
      • 2017-06-04
      • 2018-05-10
      相关资源
      最近更新 更多