Apache spark Spark 1.6,DataFrame:通过添加行来填补空白
我有一个如下所示的数据帧:Apache spark Spark 1.6,DataFrame:通过添加行来填补空白,apache-spark,dataframe,apache-spark-sql,Apache Spark,Dataframe,Apache Spark Sql,我有一个如下所示的数据帧: +-----+---+-----+ | id |ind| freq| +-----+---+-----+ |user1| 1| 5| |user2| 0| 13| |user2| 2| 4| |user3| 2| 7| |user3| 3| 45| +-----+---+-----+ +-----+---+-----+ | id |ind| freq| +-----+---+-----+ |user1| 0| 0| |
+-----+---+-----+
| id |ind| freq|
+-----+---+-----+
|user1| 1| 5|
|user2| 0| 13|
|user2| 2| 4|
|user3| 2| 7|
|user3| 3| 45|
+-----+---+-----+
+-----+---+-----+
| id |ind| freq|
+-----+---+-----+
|user1| 0| 0|
|user1| 1| 5|
|user1| 2| 0|
|user1| 3| 0|
|user2| 0| 13|
|user2| 1| 0|
|user2| 2| 4|
|user2| 3| 0|
|user3| 0| 0|
|user3| 1| 0|
|user3| 2| 7|
|user3| 3| 45|
+-----+---+-----+
列ind
具有介于0和3之间的整数值
我想为每个用户添加缺少的ind
值,同时用默认值(如0)填充freq
列,因此输出数据框如下所示:
+-----+---+-----+
| id |ind| freq|
+-----+---+-----+
|user1| 1| 5|
|user2| 0| 13|
|user2| 2| 4|
|user3| 2| 7|
|user3| 3| 45|
+-----+---+-----+
+-----+---+-----+
| id |ind| freq|
+-----+---+-----+
|user1| 0| 0|
|user1| 1| 5|
|user1| 2| 0|
|user1| 3| 0|
|user2| 0| 13|
|user2| 1| 0|
|user2| 2| 4|
|user2| 3| 0|
|user3| 0| 0|
|user3| 1| 0|
|user3| 2| 7|
|user3| 3| 45|
+-----+---+-----+
做这件事最有效的方法是什么?这不是人们能想到的最好的解决方案,但从我的头脑来看,它可以完成以下任务:
import org.apache.spark.sql.Row
val df = sc.parallelize(List(("user1",1,5),("user2", 0, 13),("user2", 2, 4),("user3", 2, 7),("user3", 3, 45))).toDF("id","ind","freq")
df.show
// +-----+---+----+
// | id|ind|freq|
// +-----+---+----+
// |user1| 1| 5|
// |user2| 0| 13|
// |user2| 2| 4|
// |user3| 2| 7|
// |user3| 3| 45|
// +-----+---+----+
val df2 = df.groupBy('id).pivot("ind").max("freq").na.fill(0)
df2.show
// +-----+---+---+---+---+
// | id| 0| 1| 2| 3|
// +-----+---+---+---+---+
// |user1| 0| 5| 0| 0|
// |user2| 13| 0| 4| 0|
// |user3| 0| 0| 7| 45|
// +-----+---+---+---+---+
val cols = df2.columns
val df3 = df2.rdd.map {
case r : Row =>
val id = r.getAs[String]("id")
cols.map(ind => (id,ind,r.getAs[Integer](ind)))
}.flatMap(_.toSeq).filter(_._2 != "id").toDF("id","ind","freq")
df3.show
// +-----+---+----+
// | id|ind|freq|
// +-----+---+----+
// |user1| 0| 0|
// |user1| 1| 5|
// |user1| 2| 0|
// |user1| 3| 0|
// |user2| 0| 13|
// |user2| 1| 0|
// |user2| 2| 4|
// |user2| 3| 0|
// |user3| 0| 0|
// |user3| 1| 0|
// |user3| 2| 7|
// |user3| 3| 45|
// +-----+---+----+
我正在使用GroupeData
中的pivot
函数,然后按列将其展平(Spark 1.6+)
PS:此解决方案未经优化,我的解决方案有很多缺点。i、 e:大量的索引、计算成本等。我刚刚遇到了这个“缺口”问题,我提出的解决方案很幼稚,所以可能效率不高,但我认为它非常简单
基本上,为了耗尽
(id,ind)
对的所有组合,我从原始DF中选择id
的不同值,然后再次选择ind
的不同值,然后交叉连接这两个结果以获得所有组合。之后,只需将结果加入到原始DF中,并用0填充所有NA。我投票决定这是向上的,因为使用Spark进行此操作会变得混乱…:)你解决这个问题了吗Rami?嗨eliasah,我已经完全改变了我的策略,所以我不再使用这个了,但是你的解决方案是正确的,正如你所说的,它可能需要一些优化。谢谢,欢迎光临!你用它来填补时间序列上的空白?是的,它可以用来填补日期之间的空白:)还有其他更有效的建议吗?