Scala 在ApacheSpark1.3中向数据帧追加一列

Scala 在ApacheSpark1.3中向数据帧追加一列,scala,apache-spark,dataframe,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.

向数据框中添加列是否可能?最有效的整洁方法是什么

更具体地说,列可以用作现有数据帧的行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")) 

我发布这个问题已经有一段时间了,似乎其他人也希望得到答案。下面是我发现的

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

sqlContext.textFile(file).
zipWithIndex().
map(case(d, i)=>i.toString + delimiter + d).
map(_.split(delimiter)).
map(s=>Row.fromSeq(s.toSeq))
关于向任何数据框追加任何列的一般情况:

Spark API中与此功能“最接近”的是
withColumn
WithColumnRename
。根据,前者通过添加列返回新的数据帧。在我看来,这是一个有点混乱和不完整的定义。这两种功能都只能在
数据帧上运行,即给定两个数据帧
df1
df2
,列为
col

val df = df1.withColumn("newCol", df1("col") + 1) // -- OK
val df = df1.withColumn("newCol", df2("col") + 1) // -- FAIL
因此,除非能够将现有数据帧中的列转换为所需的形状,否则不能使用
withColumn
withColumnRenamed
附加任意列(独立或其他数据帧)

正如上面所评论的,解决方案可能是使用
连接
——这将非常混乱,尽管可能——使用
zipWithIndex
将如上所述的唯一键连接到两个数据帧或列可能会起作用。虽然效率是


很明显,在数据框中添加列对于分布式环境来说不是一个简单的功能,可能根本就没有非常高效、简洁的方法。但我认为,即使有性能警告,仍然有这个核心功能可用是非常重要的。

我发布这个问题已经有一段时间了,似乎其他一些人也希望得到答案。下面是我发现的

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

sqlContext.textFile(file).
zipWithIndex().
map(case(d, i)=>i.toString + delimiter + d).
map(_.split(delimiter)).
map(s=>Row.fromSeq(s.toSeq))
关于向任何数据框追加任何列的一般情况:

Spark API中与此功能“最接近”的是
withColumn
WithColumnRename
。根据,前者通过添加列返回新的数据帧。在我看来,这是一个有点混乱和不完整的定义。这两种功能都只能在
数据帧上运行,即给定两个数据帧
df1
df2
,列为
col

val df = df1.withColumn("newCol", df1("col") + 1) // -- OK
val df = df1.withColumn("newCol", df2("col") + 1) // -- FAIL
因此,除非能够将现有数据帧中的列转换为所需的形状,否则不能使用
withColumn
withColumnRenamed
附加任意列(独立或其他数据帧)

正如上面所评论的,解决方案可能是使用
连接
——这将非常混乱,尽管可能——使用
zipWithIndex
将如上所述的唯一键连接到两个数据帧或列可能会起作用。虽然效率是


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

我从上面的答案中得到了帮助。但是,如果我们想更改
数据帧
,我发现它是不完整的,并且当前的API在
Spark 1.6
中几乎没有什么不同。
zipWithIndex()
返回
(行,长)
元组,该元组包含每一行和相应的索引。我们可以根据需要使用它创建新的

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

我希望这会有帮助。

我从上面的答案中得到了帮助。但是,如果我们想更改
数据帧
,我发现它是不完整的,并且当前的API在
Spark 1.6
中几乎没有什么不同。
zipWithIndex()
返回
(行,长)
元组,该元组包含每一行和相应的索引。我们可以根据需要使用它创建新的

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

我希望这会有所帮助。

不确定它是否在spark 1.3中工作,但在spark 1.5中我使用With Column:

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


df.withColumn("newName",lit("newValue"))
当我需要使用一个和dataframe的现有列不相关的值时,我会使用它


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

不确定它在spark 1.3中是否有效,但在spark 1.5中我使用With列:

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


df.withColumn("newName",lit("newValue"))
当我需要使用一个和dataframe的现有列不相关的值时,我会使用它

这与@NehaM的答案类似,但更简单,您可以使用下面的方法为数据帧中的每一行获取不同的id

df.withColumn("ID", row_number() over Window.orderBy("any column name in the dataframe"))
您还可以使用
单调地\u递增\u id
,与

df.withColumn("ID", monotonically_increasing_id())
还有一些。

您可以使用下面的方法为数据帧中的每一行获取不同的id

df.withColumn("ID", row_number() over Window.orderBy("any column name in the dataframe"))
您还可以使用
单调地\u递增\u id
,与

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

还有一些。

您找到解决方案了吗?错误是什么?这似乎是API中正确的方法。@Chet,
withColumn
应该使用相同的数据帧-也就是说,您可以使用
dataDF=dataDF.withColumn(“ID”,dataDF(“ID”).map(…)
只使用
数据帧的列,而不使用其他列