【发布时间】:2017-04-11 11:38:11
【问题描述】:
如何使用dataframe groupby agg实现以下逻辑?
ID ID2 C1 C2 C3 C4 C5 C6 .....C33
CM1 a 1 1 1 0 0 0
CM2 a 1 1 0 1 0 0
CM3 a 1 0 1 1 1 0
CM4 a 1 1 1 1 1 0
CM5 a 1 1 1 1 1 0
1k2 b 0 0 1 1 1 0
1K3 b 1 1 1 1 1 0
1K1 b 0 0 0 0 1 0
我希望我的输出 df 看起来像这样
ID ID2 C1 C2 C3 C4 C5 C6 .....C33
CM1 a 1 1 1 0 0 0
CM2 a 0 0 0 1 0 0
CM3 a 0 0 0 0 1 0
CM4 a 0 0 0 0 0 0
CM5 a 0 0 0 0 0 0
1K1 b 0 0 0 0 1 0
1k2 b 0 0 1 1 0 0
1K3 b 1 1 0 0 0 0
逻辑是根据ID2做group by,然后找到Cn为1时的最小ID然后置1,其他置0。
Cn 最高可达 C33。
如果用例类将超过限制。
我尝试过使用 mapPartitions
但是结果错了……
使用 Spark 1.6.0
添加我尝试过的代码
case class testGoods(ID: String, ID2: String, C1 : String, C2 : String)
val cartMap = new HashMap[String, Set[(String,String,String)]] with MultiMap[String,(String,String,String)]
val baseDF=hiveContext.sql(newSql)
val testRDD=baseDF.mapPartitions( partition => {
while (partition.hasNext) {
val record = partition.next()
val ID = record.getString(0)
if (ID != null && ID != "null") {
val ID2=record.getString(1)
val C1=record.getString(2)
val C2=record.getString(3)
cartMap.addBinding(ID2, (ID,C1,C2))
}
}
cartMap.iterator
})
val recordList = new mutable.ListBuffer[testGoods]()
val testRDD1=testRDD.mapPartitions( partition => {
while (partition.hasNext) {
val record = partition.next()
val ID2=record._1
val recordRow= record._2
val sortedRecordRow = TreeSet[(String,String,String)]() ++ recordRow
val dic=new mutable.HashMap[String,String]
for(v<-sortedRecordRow) {
val ID = v._1
val C1 = v._2
val C2 = v._3
if (dic.contains(ID2)){
val goodsValue=dic.get(ID2)
if("1".equals(goodsValue)){
recordList.append(new testGoods(ID, ID2, "0", C2))
}else{
dic.put(ID2,C1)
recordList.append(new testGoods(ID, ID2, C1,C2))
}
}else{
dic.put(ID2,C1)
recordList.append(new testGoods(ID, ID2, C1, C2))
}
}
}
recordList.iterator
})
再次编辑
原始数据集有数百万个ID,按ID分组后,每个ID2可能有2~300个数据。
【问题讨论】:
-
你能添加一些你试过的代码吗?
-
当然,我添加了一些代码并编辑了示例。
标签: scala apache-spark apache-spark-sql spark-dataframe