是否可以在spark sql中以编程方式对列进行别名?

时间:2015-07-21 12:07:43

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

在spark SQL(可能只有HiveQL)中,可以做到:

select sex, avg(age) as avg_age
from humans
group by sex

这会产生DataFrame,其中包含名为"sex""avg_age"的列。

如果avg(age)不使用文本SQL,"avg_age"如何别名?

修改 在零323的回答之后,我需要添加以下约束:

要重命名的列名称可能未知/保证甚至无法寻址。在文本SQL中,使用"选择EXPR作为NAME"删除了具有EXPR中间名称的要求。在上面的例子中也是这种情况,其中" avg(年龄)"可以获得各种自动生成的名称(在spark发布和sql-context后端之间也有所不同)。

4 个答案:

答案 0 :(得分:32)

我们假设human_df是人类的DataFrame。自Spark 1.3开始:

human_df.groupBy("sex").agg(avg("age").alias("avg_age"))

答案 1 :(得分:17)

如果您希望重命名单个列,则可以使用withColumnRenamed方法:

case class Person(name: String, age: Int)

val df = sqlContext.createDataFrame(
    Person("Alice", 2) :: Person("Bob", 5) :: Nil) 
df.withColumnRenamed("name", "first_name")

或者,您可以使用alias方法:

import org.apache.spark.sql.functions.avg

df.select(avg($"age").alias("average_age")) 

你可以用小帮手进一步:

import org.apache.spark.sql.Column

def normalizeName(c: Column) = {
  val pattern = "\\W+".r
  c.alias(pattern.replaceAllIn(c.toString, "_"))
}

df.select(normalizeName(avg($"age")))

答案 2 :(得分:9)

原来def toDF(colNames: String*): DataFrame正是如此。粘贴2.11.7文档:

def toDF(colNames: String*): DataFrame

Returns a new DataFrame with columns renamed. This can be quite
convenient in conversion from a RDD of tuples into a DataFrame
with meaningful names. For example:

    val rdd: RDD[(Int, String)] = ...
    rdd.toDF()  // this implicit conversion creates a DataFrame
                // with column name _1 and _2
    rdd.toDF("id", "name")  // this creates a DataFrame with
                            // column name "id" and "name"

答案 3 :(得分:1)

匿名列,例如由avg(age)生成而没有AS avg_age的列,会自动分配名称。正如您在问题中指出的那样,名称是特定于实现的,由命名策略生成。如果需要,您可以编写能够嗅探环境并实例化适当发现的代码。根据特定的命名策略重命名策略。它们并不多。

在带有HiveContext的Spark 1.4.1中,格式为" _c N "其中 N 是表中匿名列的位置。在您的情况下,名称将为_c1