【问题标题】:Multiple-columns operations in SparkSpark 中的多列操作
【发布时间】:2017-09-20 16:33:25
【问题描述】:

使用 Python 的 Pandas,可以一次性对多列进行批量操作,如下所示:

# assuming we have a DataFrame with, among others, the following columns
cols = ['col1', 'col2', 'col3', 'col4', 'col5', 'col6', 'col7', 'col8']
df[cols] = df[cols] / df['another_column']

在 Scala 中使用 Spark 是否有类似的功能?

目前我最终会做:

val df2 = df.withColumn("col1", $"col1" / $"another_column")
            .withColumn("col2", $"col2" / $"another_column")
            .withColumn("col3", $"col3" / $"another_column")
            .withColumn("col4", $"col4" / $"another_column")
            .withColumn("col5", $"col5" / $"another_column")
            .withColumn("col6", $"col6" / $"another_column")
            .withColumn("col7", $"col7" / $"another_column")
            .withColumn("col8", $"col8" / $"another_column")

【问题讨论】:

    标签: scala apache-spark


    【解决方案1】:

    您可以使用foldLeft对列列表进行如下处理:

    val df = Seq(
      (1, 20, 30, 4),
      (2, 30, 40, 5),
      (3, 10, 30, 2)
    ).toDF("id", "col1", "col2", "another_column")
    
    val cols = Array("col1", "col2")
    
    val df2 = cols.foldLeft( df )( (acc, c) =>
      acc.withColumn( c, df(c) / df("another_column") )
    )
    
    df2.show
    +---+----+----+--------------+
    | id|col1|col2|another_column|
    +---+----+----+--------------+
    |  1| 5.0| 7.5|             4|
    |  2| 6.0| 8.0|             5|
    |  3| 5.0|15.0|             2|
    +---+----+----+--------------+
    

    【讨论】:

      【解决方案2】:

      为了完整性:与@Leo C 的版本略有不同,不使用foldLeft,而是使用单个select 表达式:

      import org.apache.spark.sql.functions._
      import spark.implicits._
      
      val toDivide = List("col1", "col2")
      val newColumns = toDivide.map(name => col(name) / col("another_column") as name)
      
      val df2 = df.select(($"id" :: newColumns) :+ $"another_column": _*)
      

      产生相同的输出。

      【讨论】:

        【解决方案3】:

        您可以在操作列上使用普通的select。该解决方案与 Python Panda 解决方案非常相似。

        //Define the dataframe df1
        case class ARow(col1: Int, col2: Int, anotherCol: Int)
        val df1 = spark.createDataset(Seq(
          ARow(1, 2, 3), 
          ARow(4, 5, 6), 
          ARow(7, 8, 9))).toDF
        
        // Perform the operation using a map
        val cols = Array("col1", "col2")
        val opCols = cols.map(c => df1(c)/df1("anotherCol"))
        
        // Select the columns operated
        val df2 = df1.select(opCols: _*)
        

        df2 上的.show

        df2.show()
        +-------------------+-------------------+
        |(col1 / anotherCol)|(col2 / anotherCol)|
        +-------------------+-------------------+
        | 0.3333333333333333| 0.6666666666666666|
        | 0.6666666666666666| 0.8333333333333334|
        | 0.7777777777777778| 0.8888888888888888|
        +-------------------+-------------------+
        

        【讨论】:

        • 它也与我 40 分钟前发布的非常相似(相同)...
        • 没看到。你介意我编辑另一个吗?它有不必要的导入并且 select 是不可读的。
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2018-08-06
        • 1970-01-01
        • 2014-06-05
        • 2020-12-13
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多