2015-07-21 24 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

相關問題