2015-07-21 85 views
14

在火花SQL(也许只有HiveQL)一个可以这样做:是否有可能在spark sql中以编程方式别名列?

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

,这将导致一个名为"sex""avg_age"DataFrame

avg(age)如何在不使用文本SQL的情况下将其别名为"avg_age"

编辑: zero323的回答后,我需要添加约束:

列将要更名为的名字可能不知道/保证,甚至可寻址。在文本SQL中,使用“选择EXPR作为名称”取消了为EXPR设置中间名称的要求。在上面的例子中也是这种情况,其中“avg(age)”可以获得各种自动生成的名称(它们在spark版本和sql-context后端中也有所不同)。

+0

您可以为您的df添加别名。 –

回答

24

让我们假设human_df是人类的数据框。由于Spark 1.3:

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

这是Scala吗?它看起来像Python。 – summerbulb

7

原来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" 
11

如果你喜欢重命名一列,可以使用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"))) 
1

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

在火花1.4.1与HiveContext,格式为“_c Ñ”,其中Ñ是在表中的匿名列的位置。在你的情况下,这个名字应该是_c1

相关问题