Spark Scala Dataframe:删除第n条记录

时间:2016-04-05 04:46:13

标签: scala apache-spark dataframe apache-spark-sql rdd

是否可以在不使用collect的情况下从数据框中删除第n行,然后转换回dataFrame。我想避免使用collect,因为我有一个大型数据集。

val arr=df.collect().toBuffer
arr.remove(13)

可能以某种方式我可以转换回dataframe.Is有更简单的方法吗? 我试过zipwithIndex,但dataFrame不支持zipwithIndex

value zipWithIndex is not a member of org.apache.spark.sql.DataFrame

2 个答案:

答案 0 :(得分:3)

据我所知,DataFrame不支持这一点,您需要使用RDD API。您可以在之后转换回DataFrame。

请注意,这与使用将所有数据复制到驱动程序的collect非常不同。

val filteredRdd = input.rdd.zipWithIndex().collect { case (r, i) if i != 13 => r }
val newDf = sqlContext.createDataFrame(filteredRdd, input.schema)

(这里使用的collect不是向驱动程序收集数据的那个,它在一次调用中应用部分函数进行过滤和映射)。

免责声明:请记住,Spark中的DataFrames就像RDD,因为它们是不可变的数据结构。因此,诸如创建新列或删除行,或尝试通过索引访问DataFrame中的单个元素之类的东西不可能存在,只是因为这种做法违背了Spark的原则。不要忘记您使用的是分布式数据结构,而不是内存中的随机访问数据结构。

要清楚,这并不意味着你不能使用Spark做同样的事情(即创建一个新的列),这意味着你必须考虑不可变/分布式并重写你的部分内容代码,主要是那些不纯粹被认为是数据流转换的部分。

答案 1 :(得分:0)

在Spark术语中我会说转换RDD比转换它更好。 这是一个建议使用过滤方法来有效地执行此操作的示例。 您肯定需要为此示例提供索引列。

import org.apache.spark.sql._

val list = Seq(("one", 1), ("two", 2), ("three", 3),("four", 4),("five", 5))
val sqlContext = new SQLContext(sc)

val numdf = sqlContext.createDataFrame(list)
numdf.printSchema()

root
 |-- _1: string (nullable = true)
 |-- _2: integer (nullable = false)

newdf = numdf.filter(numdf("_2")<2 or numdf("_2")>2).show()

这是我的#bluemix notebook

谢谢,

查尔斯。