我有一个时间序列数据帧存储在一个分区
+-------------+------+----+-------+
| TimeStamp| X| Y| Z|
+-------------+------+----+-------+
|1448949705421|-35888|4969|3491754|
|1448949705423|-35081|2795|3489177|
|1448949705425|-35976|5830|3488618|
|1448949705426|-36927|4729|3491807|
|1448949705428|-36416|6246|3490364|
|1448949705429|-36073|7067|3491556|
|1448949705431|-38553|3714|3489545|
|1448949705433|-39008|3034|3490230|
|1448949705434|-35295|4005|3489426|
|1448949705436|-36397|5076|3490941|
+-------------+------+----+-------+
我想将这个数据帧重新划分为10个分区,这样第一个分区大约有前1/10行,第二个分区大约有第二个1/10行,依此类推。
我能想到的一种方式是:
var df = ???
// add index to df
val rdd = df.rdd.zipWithIndex().map(indexedRow =>
Row.fromSeq(indexedRow._2.toLong +: indexedRow._1.toSeq))
val newstructure = StructType(Seq(StructField("rn", LongType, true)).++(df.schema.fields))
val dfWithIndex = sqlContext.createDataFrame(rdd, newstructure)
// create a group number using the index
val udfToInt = udf[Int, Double](_.toInt)
val dfWithGrp = dfWithIndex.withColumn("group", udfToInt($"rn" / (df.count / 10)))
// repartition by the "group" column
val partitionedDF = dfWithGrp.repartition(10, $"group")
我能想到的另一种方法是使用分区器:
//After creating a group number
val grpIndex = dfWithGrp.schema.fields.size - 1
val partitionedRDD = dfWithGrp.rdd.map(r => (r.getInt(grpIndex), r))
.partitionBy(new HashPartitioner(10))
.values
但它们似乎效率不高,因为我们需要先添加索引,然后使用索引创建一个组号。有没有办法在不添加额外的组列的情况下执行此操作?