是否可以在 spark sql 中以编程方式对列进行别名?
Posted
技术标签:
【中文标题】是否可以在 spark sql 中以编程方式对列进行别名?【英文标题】:Is it possible to alias columns programmatically in spark sql? 【发布时间】:2015-07-21 12:07:42 【问题描述】:在 spark SQL(也许只有 HiveQL)中可以做到:
select sex, avg(age) as avg_age
from humans
group by sex
这将导致 DataFrame
的列名为 "sex"
和 "avg_age"
。
如何在不使用文本 SQL 的情况下将 avg(age)
别名为 "avg_age"
?
编辑: 在 zero323 的回答之后,我需要添加以下约束:
要重命名的列的名称可能未知/无法保证,甚至无法寻址。在文本 SQL 中,使用“select EXPR as NAME”消除了对 EXPR 具有中间名称的要求。在上面的示例中也是如此,其中“avg(age)”可以获得各种自动生成的名称(在 spark 版本和 sql-context 后端中也会有所不同)。
【问题讨论】:
您可以为您的 df 添加别名。 【参考方案1】:假设human_df
是人类的DataFrame。从 Spark 1.3 开始:
human_df.groupBy("sex").agg(avg("age").alias("avg_age"))
【讨论】:
这是 Scala 吗?它看起来像 Python。【参考方案2】:如果您希望重命名单个列,可以使用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")))
【讨论】:
【参考方案3】:原来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"
【讨论】:
【参考方案4】:匿名列,例如由avg(age)
生成的没有AS avg_age
的列,会自动分配名称。正如您在问题中指出的那样,名称是特定于实现的,由命名策略生成。如果需要,您可以编写代码来嗅探环境并根据特定的命名策略实例化适当的发现和重命名策略。数量不多。
在带有HiveContext
的Spark 1.4.1 中,格式为“_cN”,其中N 是匿名列在表中的位置。在您的情况下,名称将是 _c1
。
【讨论】:
以上是关于是否可以在 spark sql 中以编程方式对列进行别名?的主要内容,如果未能解决你的问题,请参考以下文章
在 Python 中以编程方式启动 HiveThriftServer
如何在 Entity Framework 6 中以编程方式创建与 MS SQL 的连接字符串?