【问题标题】:org.apache.spark.sql.AnalysisException:org.apache.spark.sql.AnalysisException:
【发布时间】:2020-07-10 22:26:04
【问题描述】:
 df.withColumn(x, when($"x" > 75, $"x" + 10).otherwise($"x")).show()
org.apache.spark.sql.AnalysisException: cannot resolve '`x`' given input columns: [Name, Subject, Marks];;
'Project [Name#7, Subject#8, CASE WHEN ('x > 75) THEN ('x + 10) ELSE 'x END AS Marks#38]

scala> df.show()
+----+-------+-----+
|Name|Subject|Marks|
+----+-------+-----+
| Ram|Physics|   80|
|Sham|English|   90|
|Ayan|   Math|   70|
+----+-------+-----+


scala> x
res6: String = Marks

我想传递一个变量作为参数并存储数据框的列值。并根据该参数检查条件、计算值并替换该数据框中具有相同名称的列。

实际上更大的问题是,有多个同名的列,例如 "col1","col2","col3".... 我会将这些列存储在一个数组中,并通过传递数据帧操作中的数组。但就目前而言。如果可以在 spark-scala 中处理,请告诉我问题的解决方案。

【问题讨论】:

标签: scala dataframe apache-spark


【解决方案1】:

试试 String interpolation col({s"${x}"})

Example:

val df=Seq(("Ram","Physics",80),("Sham","English",90),("Ayan","Math",70)).toDF("Name","Subject","Marks")

df.show()
//+----+-------+-----+
//|Name|Subject|Marks|
//+----+-------+-----+
//| Ram|Physics|   80|
//|Sham|English|   90|
//|Ayan|   Math|   70|
//+----+-------+-----+

import org.apache.spark.sql.functions._
val x:String = "Marks"

df.withColumn(x, when(col(s"${x}") > 75, col(s"${x}") + 10).otherwise(col(s"${x}"))).show()
//+----+-------+-----+
//|Name|Subject|Marks|
//+----+-------+-----+
//| Ram|Physics|   90|
//|Sham|English|  100|
//|Ayan|   Math|   70|
//+----+-------+-----+

【讨论】:

  • 我们可以关闭accepting the answer as owner?的线程
  • @Shu,因为我使用的是 DBR 6.5、Spark 2.4.5 并且无法正常工作,所以它在哪个 spark 版本中工作。错误:未找到:值 x df.withColumn(x, when(col(s"${x}") > 75, col(s"${x}") + 10).otherwise(col(s"${ x}"))).show()
  • @sathiyarajan,我在复制val x:String = "Marks" 时错过了定义variable x 并更新了答案.. 请立即查看..!
  • @Shu,col 内部不需要字符串插值。我们可以直接使用functions.col中定义为字符串的变量。请检查我的答案
  • @Shu,谢谢。如果您有解决方案,只想知道一件事。如果我们想遍历列,那么每次我们必须定义一个新的数据框,因为数据框是不可变的。有什么方法可以声明数据框数组。
【解决方案2】:

为了更好地理解,我将列分隔为 requiredColumnsallColumns

检查下面的代码。

scala> df.show(false)
+----+-------+-----+
|Name|Subject|Marks|
+----+-------+-----+
|Ram |Physics|80   |
|Sham|English|90   |
|Ayan|Math   |70   |
+----+-------+-----+
scala> val requiredColumns = Set("Marks")
requiredColumns: scala.collection.immutable.Set[String] = Set(Marks)
scala> val allColumns = df.columns
allColumns: Array[String] = Array(Name, Subject, Marks)
scala> 
val columnExpr =  allColumns
                    .filterNot(requiredColumn(_))
                    .map(col(_)) ++ requiredColumns
                    .map(c => when(col(c) > 75,col(c) + 10).otherwise(col(c)).as(c))

输出

scala> df.select(columnExpr:_*).show(false)
+----+-------+-----+
|Name|Subject|Marks|
+----+-------+-----+
|Ram |Physics|90   |
|Sham|English|100  |
|Ayan|Math   |70   |
+----+-------+-----+

【讨论】:

    【解决方案3】:

    如下使用functions.col-

     df1.show(false)
    
        /**
          * +----+-------+-----+
          * |Name|Subject|Marks|
          * +----+-------+-----+
          * |Ram |Physics|80   |
          * |Sham|English|90   |
          * |Ayan|Math   |70   |
          * +----+-------+-----+
    */
    val x = "Marks"
        // use functions.col
        df1.withColumn(x, when(col(x) > 75, col(x) + 10).otherwise(col(x)))
          .show()
    
        /**
          * +----+-------+-----+
          * |Name|Subject|Marks|
          * +----+-------+-----+
          * | Ram|Physics|   90|
          * |Sham|English|  100|
          * |Ayan|   Math|   70|
          * +----+-------+-----+
          */
    

    【讨论】:

    • 谢谢。如果您有解决方案,只想知道一件事。如果我们想遍历列,那么每次我们必须定义一个新的数据框,因为数据框是不可变的。有什么方法可以声明数据框数组。
    • 不确定我是否理解正确。你总是可以这样做的。但想知道意图。我建议使用示例 i/p 和 o/p 提出新的后续查询。正确描述问题
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-06-19
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多