【问题标题】:Spark SQL: Select with arithmetic on column values and type casting?Spark SQL:使用列值的算术选择和类型转换?
【发布时间】:2016-06-13 05:41:40
【问题描述】:

我将 Spark SQL 与 DataFrames 一起使用。有没有办法用一些算术来做一个选择语句,just as you can in SQL

例如,我有下表:

var data = Array((1, "foo", 30, 5), (2, "bar", 35, 3), (3, "foo", 25, 4))
var dataDf = sc.parallelize(data).toDF("id", "name", "value", "years")

dataDf.printSchema
// root
//  |-- id: integer (nullable = false)
//  |-- name: string (nullable = true)
//  |-- value: integer (nullable = false)
//  |-- years: integer (nullable = false)

dataDf.show()
// +---+----+-----+-----+
// | id|name|value|years|
// +---+----+-----+-----+
// |  1| foo|   30|    5|
// |  2| bar|   35|    3|
// |  3| foo|   25|    4|
//+---+----+-----+-----+

现在,我想做一个 SELECT 语句来创建一个新列,并对现有列执行一些算术运算。例如,我想计算比率value/years。我需要先将价值(或年)转换为双倍。我试过这个语句,但它不会解析:

dataDf.
    select(dataDf("name"), (dataDf("value").toDouble/dataDf("years")).as("ratio")).
    show()

<console>:35: error: value toDouble is not a member of org.apache.spark.sql.Column
              select(dataDf("name"), (dataDf("value").toDouble/dataDf("years")).as("ratio")).

我在“How to change column types in Spark SQL's DataFrame?”看到了一个类似的问题,但这不是我想要的。

【问题讨论】:

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


    【解决方案1】:

    更改Column 类型的正确方法是使用cast 方法。它可以采用描述字符串:

    dataDf("value").cast("double") / dataDf("years")
    

    DataType:

    import org.apache.spark.sql.types.DoubleType
    
    dataDf("value").cast(DoubleType) / dataDf("years")
    

    【讨论】:

    • 谢谢。这种铸造方法有效。 dataDf.select(dataDf("name"), (dataDf("value").cast("double")/dataDf("years")).as("ratio")).show
    【解决方案2】:

    如果不需要使用select 方法,您可以使用withColumn

    val resDF = dataDf.withColumn("result", col("value").cast("double") / col("years"))
    resDF.show
    
    //+---+----+-----+-----+------------------+
    //| id|name|value|years|            result|
    //+---+----+-----+-----+------------------+
    //|  1| foo|   30|    5|               6.0|
    //|  2| bar|   35|    3|11.666666666666666|
    //|  3| foo|   25|    4|              6.25|
    //+---+----+-----+-----+------------------+
    

    如果需要使用select,一个选项可能是:

    val exprs = dataDf.columns.map(col(_)) ++ List((col("value").cast("double") / col("years")).as("result"))
    dataDf.select(exprs: _*).show
    
    //+---+----+-----+-----+------------------+
    //| id|name|value|years|            result|
    //+---+----+-----+-----+------------------+
    //|  1| foo|   30|    5|               6.0|
    //|  2| bar|   35|    3|11.666666666666666|
    //|  3| foo|   25|    4|              6.25|
    //+---+----+-----+-----+------------------+
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2019-07-13
      • 2023-03-29
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-08-22
      • 1970-01-01
      相关资源
      最近更新 更多