【问题标题】:Apply map transformation on specific columns while retaining other columns in Scala在特定列上应用映射转换,同时保留 Scala 中的其他列
【发布时间】:2021-11-26 03:16:01
【问题描述】:

我有一个 map 函数,我想将它应用于 dataframe 中的特定列。假设我有一个数据框 ABC,如下所示:

A B
foo 1
bar 4
biz 3

我想将B列的所有元素乘以2,同时保留A列得到如下输出:

A B
foo 2
bar 8
biz 6

我知道如何选择数据框中的 B 列并使用 map 转换元素,如下面的代码所示: ABC.select("B").columns.map(c => c*2)

但我的问题是我也无法获得 A 列。

我第一次尝试使用这样的东西: ABC.select("A", (ABC.select("B").columns.map(c => c*2):_*)

但是,这会引发“select”方法无法重载的错误——这是公平的,因为它不接受 Array[Column] 类型的参数。然后我尝试了这个:

val arrayB = Array("B")

ABC.select(ABC.columns.map(c => if (arrayB.contains(c)) c*2 else col(c)):_*)

这确实有效并将结果返回给我,但我想知道是否有更好的方法来做到这一点。提前致谢!

【问题讨论】:

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


    【解决方案1】:

    试试这个:

    import org.apache.spark.sql.functions.{col, expr}
    
    ABC.select(col("A"), expr("B * 2").as("B"))
    

    您也可以使用selectExpr("A, B * 2 as B")(甚至可能是col("B") * 2?),但我更喜欢第一个,它更清洁且更易于维护。

    更新(因为最新的 cmets): 据我了解,您可能希望将特定函数应用于 df 中的所有列,如果我是正确的,那么我建议您这样做:

    import org.apache.spark.{Column, DataFrame}
    import org.apache.spark.sql.functions._
    
    // This is the base function which will be curried //
    def applyColumnTransformation(column: Column)(transformation: Column => Column): Column = transformation(column)
    
    val myTransformation: Column => Column = inputColumn => {
        // your logic here, for instance:
        inputColumn * 2  // you can pass name alias here, like (inputColumn * 2).as(inputColumn.toString)
    }
    
    def applyMyTransformation(column: Column): Column = applyColumnTransformation(column)(myTransformation)
    

    现在你已经拥有了你想要的一切,只需这样做:

    val allColumns: Seq[Column] = myDf.columns.map(myDf.col)
    val transformedColumns: Seq[Column] = allColumns.map(applymyTransformation)
    myDf.select(transformedColumns: _*)
    

    顺便说一下,一定要看看functions包,它实际上有很多有用的功能。

    【讨论】:

    • 感谢您抽出宝贵时间回答@AminMal。在我的问题中,我给出了 B 的示例,但在我的实际场景中,我有很多列需​​要应用转换。我可以在您的回答中提到的 expr() 块中包含地图转换吗?
    • 不客气,我不确定你所说的地图转换是什么意思,但据我所知,expr 函数是某种魔法,你可以做任何你想做的事情,数学表达式、类似 SQL 的类型转换、强制转换和许多其他事情。你能告诉我地图转换是什么意思吗?
    • 通过映射转换我的意思是我想在所有列上执行一个函数,例如columns.map(c => myFunction(c))。 myFunction 在我的实际场景中非常复杂,这就是为什么我可能无法将它包含在 expr() 块本身中的原因。因此,我希望能够在列上调用函数。它不一定是地图转换,但这是我知道在多列上调用相同函数的唯一方法。因此,我的问题是否可以在 expr() 块中调用 map?或者有什么办法可以做到这一点?
    • @kiarraa95 刚刚更新了答案,请看一下,让我知道它是否有效
    猜你喜欢
    • 2022-11-23
    • 2021-05-09
    • 1970-01-01
    • 1970-01-01
    • 2011-09-25
    • 2018-07-23
    • 2019-11-18
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多