繁体   English   中英

部分RDD的scala操作

[英]scala operations on part of RDD

我是Scala的新手,我正在尝试为项目做点什么:

我生成了一个RDD:RDD

[UserID1, Date1, Value1]
[UserID1, Date2, Value2]
[UserID1, Date3, Value3]
[UserID2, Date1, Value1]
[UserID3, Date1, Value1]

我希望在这个生成RDD的RDD上运行一个函数

[UserID1, FunctionResult1, FunctionResult2]
[UserID1, FunctionResult3, FunctionResult4]
[UserID2, FunctionResult1, FunctionResult2]

这个函数应该工作的方式是:1,groupBy UserID,并按升序排序日期(我已经将日期格式化为INT:20150225。

2,取第一个日期和第二个日期,找到它们之间的日期数。

3,取第一个值和第二个值,找出它们之间的差异。

将这些值记录到功能结果中,继续处理第二个日期和第三个日期以及第二个和第三个值。

如果输入是5行x 3列,则结果应为4行x 3列。

到目前为止,我已尝试在RDD上执行reduceByKey,但它只在输出中生成一行。 所以我想知道是否还有其他有效的方法可以做到这一点,也许没有循环? 我目前的代码看起来像这样

val basicsearchprofile = basicsearch.map(x=>(x._1,(x._2,x._3).reduceByKey((a,b)=> funcdiff(a,b))

// x._1是用户ID,x._2是Date,x._3是Value;

def funcdiff(a:(Date,Value),b:(Date,Value)):(Day,value) =
  {
        val diffdays = (b._1%100 - a._1%100) + ((b._1/100)%100)- (a._1/100)%100))*30 + ((a._1/10000)%100 - (b._1/10000)%100))*365 //difference between days

        val diffvalue = Math.abs(a._2 - b._2)
    }
      (diffdays diffvalue)
  }

我假设函数funcdiff的返回值会成对地减少每个事件,并最终将它减少到一行? 是否可以将函数funcdiff应用到第二行的第一行,记录答案; 接下来将它应用于第二行和第三行......依此类推,使得返回的结果是[ID,Datediff,Valuediff]的RDD

提前致谢

Spark进程行并行。 因为你必须做row2-row1,row3-row2,我认为你不能再并行工作了。 因此,您必须忘记Spark,使用普通Scala并在单个节点上处理整个用户数据(尽管可以并行处理每个用户)。 例如:

// First, group by user with Spark
case class Info(userId:String, date:Int, value:Int)
val infos=List(
    Info("john",20150221,10),
    Info("mary",20150221,11),
    Info("john",20150222,12),
    Info("mary",20150223,15),
    Info("john",20150223,14),
    Info("john",20150224,16),
    Info("john",20150225,18),
    Info("mary",20150225,17))
val infoRdd=sc.parallelize(infos)
val infoByIdRdd=infoRdd.map( info => (info.userId, info)).groupByKey()
// Then use plain Scala to process each user data
def infoDeltas(infos:List[Info]) = {
    // Transform [Info1, Info2, Info3] into [(Info1,Info2),(Info2,Info3)]
    val accZero:(Option[Info],List[(Info,Info)])=(None,List())
    def accInfo(last:Option[Info], list:List[(Info,Info)], info:Info) = {
        last match {
            case None => (Some(info), list)
            case Some(lastInfo) => (Some(info), list:+(lastInfo,info))
        }
    }
    val infoIntervals=infos.foldLeft(accZero)( 
        (acc,info) => accInfo(acc._1, acc._2, info)
    )._2
    // Transform [(Info1,Info2),(Info2,Info3)] into [Info2-Info1,Info3-Info2]
    infoIntervals.map(interval => interval match {case (before,after) => Info(after.userId,after.date-before.date,after.value-before.value)})
}
val infoDeltasByIdRdd=infoByIdRdd.mapValues(infos => infoDeltas(infos.toList))

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM