如何将Spark列的名称获取为String?

时间:2018-11-26 11:00:05

标签: scala apache-spark

我想写一种方法来舍入一个数字列而不做类似的事情:

df
.select(round($"x",2).as("x"))

因此,我需要有一个可重复使用的column-expression,例如:

def roundKeepName(c:Column,scale:Int) = round(c,scale).as(c.name)

很遗憾,c.name不存在,因此上述代码无法编译。我找到了ColumName的解决方案:

 def roundKeepName(c:ColumnName,scale:Int) = round(c,scale).as(c.string.name)

但是我该如何使用Column(如果我使用col("x")而不是$"x"来生成)

2 个答案:

答案 0 :(得分:1)

不确定问题是否真的得到了回答。您的函数可以这样实现(toString返回列的名称):

def roundKeepname(c:Column,scale:Int) = round(c,scale).as(c.toString)

如果您不喜欢依赖toString,这是一个更强大的版本。您可以依赖基础表达式,将其强制转换为NamedExpression并取其名称。

import org.apache.spark.sql.catalyst.expressions.NamedExpression
def roundKeepname(c:Column,scale:Int) = 
    c.expr.asInstanceOf[NamedExpression].name

它有效:

scala> spark.range(2).select(roundKeepname('id, 2)).show
+---+
| id|
+---+
|  0|
|  1|
+---+  

答案 1 :(得分:-1)

更新

使用BlueSheepToken提供的解决方案,这里是假设所有“双”列都可以动态地实现的方法。

scala> val df = Seq((1.22,4.34,8.93),(3.44,12.66,17.44),(5.66,9.35,6.54)).toDF("x","y","z")
df: org.apache.spark.sql.DataFrame = [x: double, y: double ... 1 more field]

scala> df.show
+----+-----+-----+
|   x|    y|    z|
+----+-----+-----+
|1.22| 4.34| 8.93|
|3.44|12.66|17.44|
|5.66| 9.35| 6.54|
+----+-----+-----+


scala>  df.columns.foldLeft(df)( (acc,p)  => (acc.withColumn(p+"_t",round(col(p),1)).drop(p).withColumnRenamed(p+"_t",p))).show
+---+----+----+
|  x|   y|   z|
+---+----+----+
|1.2| 4.3| 8.9|
|3.4|12.7|17.4|
|5.7| 9.4| 6.5|
+---+----+----+


scala>