在Apache Spark 1.3中向Data Frame附加一列

时间:2015-04-07 03:59:38

标签: scala apache-spark dataframe

是否有可能以及将数据库添加到数据框的最有效的方法是什么?

更具体地说,列可以作为现有数据框的行ID。

在简化的情况下,从文件读取而不是标记它,我可以想到如下(在Scala中),但它完成有错误(在第3行),并且无论如何看起来不是最好的路线:

var dataDF = sc.textFile("path/file").toDF() 
val rowDF = sc.parallelize(1 to DataDF.count().toInt).toDF("ID") 
dataDF = dataDF.withColumn("ID", rowDF("ID")) 

4 个答案:

答案 0 :(得分:50)

自从我发布问题以来已经有一段时间了,似乎其他一些人也希望得到答案。以下是我发现的内容。

因此,最初的任务是将一个带有行标识符的列(基本上是一个序列1 to numRows)附加到任何给定的数据帧,因此可以跟踪行的顺序/存在(例如,当您进行采样时)。这可以通过以下方式实现:

sqlContext.textFile(file).
zipWithIndex().
map(case(d, i)=>i.toString + delimiter + d).
map(_.split(delimiter)).
map(s=>Row.fromSeq(s.toSeq))

关于将任何列附加到任何数据框的一般情况:

"最近" Spark API中的此功能包括withColumnwithColumnRenamed。根据{{​​3}},前通过添加列返回新的DataFrame。在我看来,这是一个有点混乱和不完整的定义。这两个函数都只能在this数据框上运行,即给定两个数据框df1df2col

val df = df1.withColumn("newCol", df1("col") + 1) // -- OK
val df = df1.withColumn("newCol", df2("col") + 1) // -- FAIL

因此,除非您能够将现有数据框中的列转换为所需的形状,否则您无法使用withColumnwithColumnRenamed附加任意列(独立或其他数据框) )。

正如上面评论的那样,解决方法可能是使用join - 这可能会非常混乱,尽管可能 - 将上面的唯一键与zipWithIndex一起附加到数据框或列可能有用。虽然效率很高......

很明显,在数据框中附加一个列并不是分布式环境的简单功能,可能根本就没有非常有效,简洁的方法。但我认为,即使有性能警告,提供此核心功能仍然非常重要。

答案 1 :(得分:27)

不确定它是否适用于spark 1.3但是在spark 1.5中我使用了withColumn:

import sqlContext.implicits._
import org.apache.spark.sql.functions._


df.withColumn("newName",lit("newValue"))

当我需要使用与数据帧的现有列

无关的值时,我会使用它

这类似于@ NehaM的答案,但更简单

答案 2 :(得分:6)

我从上面的回答中得到了帮助。但是,如果我们想要更改DataFrame并且当前API在Spark 1.6中略有不同,我发现它不完整。 zipWithIndex()返回Tuple (Row, Long),其中包含每一行和相应的索引。我们可以根据需要使用它来创建新的Row

val rdd = df.rdd.zipWithIndex()
             .map(indexedRow => Row.fromSeq(indexedRow._2.toString +: indexedRow._1.toSeq))
val newstructure = StructType(Seq(StructField("Row number", StringType, true)).++(df.schema.fields))
sqlContext.createDataFrame(rdd, newstructure ).show

我希望这会有所帮助。

答案 3 :(得分:3)

您可以将row_numberWindow function一起使用,以获取数据框中每行的不同ID。

df.withColumn("ID", row_number() over Window.orderBy("any column name in the dataframe"))

您也可以使用monotonically_increasing_id

相同
df.withColumn("ID", monotonically_increasing_id())

还有一些other ways