具体的数据和算法见:http://blog.fens.me/rhadoop-mapreduce-rmr/
这里仅给出Rhadoop代码的部分注释:
#加载rmr2包 library(rmr2) #输入数据文件 train<-read.csv(file="small.csv",header=FALSE) names(train)<-c("user","item","pref") #使用rmr的hadoop格式,hadoop是默认设置。 rmr.options(backend = 'hadoop') #把数据集存入HDFS train.hdfs = to.dfs(keyval(train$user,train)) from.dfs(train.hdfs) #####STEP 1, 建立物品的同现矩阵##### # 1) 按用户分组,得到所有物品出现的组合列表。 train.mr<-mapreduce(train.hdfs, map = function(k, v) {keyval(k,v$item)}, #map形成<user,item> reduce=function(k,v){ m<-merge(v,v);#通过merge合并item和item形成所有可能的两两物品组合 keyval(m$x,m$y);#两两组合一个为key一个为value } ) from.dfs(train.mr) # 2) 对物品组合列表进行计数,建立物品的同现矩阵 step2.mr<-mapreduce( train.mr, map = function(k, v) { d<-data.frame(k,v)#将同现矩阵转为数据框,两两物品为一行 d2<-ddply(d,.(k,v),count)#分组求次数 #ddply(.data,.variables,.fun)针对数据.data按照分组.variables进行fun统计 key<-d2$k val<-d2 keyval(key,val)#key为item1,value是整个统计结果:item1 item2 frequency,这里item1表示物品1 }#注意这里reduce=NULL ) from.dfs(step2.mr) ##### 2. 建立用户对物品的评分矩阵#### train2.mr<-mapreduce( train.hdfs, #key为user,value为三列:user item pref map = function(k, v) { #df<-v[which(v$user==3),] df<-v#user item pref key<-df$item val<-data.frame(item=df$item,user=df$user,pref=df$pref) keyval(key,val)#key为item,value为:item user pref } ) from.dfs(train2.mr)#key为item,value为:item user pref ####3. 合并同现矩阵 和 评分矩阵#### eq.hdfs<-equijoin( #equijoin(left.input,right.input,map.left,map.right,outer=c("","left","right","full"))from.dfs(result.mr) #left.input和right.input表示左边输入数据和右边输入数据 #map.left是一个函数作用与左边输入数据,返回的key作为连接关键字,map.right针对右边输入数据 #outer表示两边数据的连接方式 left.input=step2.mr, #其中step.mr:key为item1,value是整个统计结果:item1 item2 frequency right.input=train2.mr,#train2.mr:key为item,value为:item user pre map.left=function(k,v){ keyval(k,v) }, map.right=function(k,v){ keyval(k,v) }, outer = c("left")#左连接(左边输入数据行全部存在) ) from.dfs(eq.hdfs)#返回的结果key=NULL,value:item1 item2 frequency item=item1 user pref ####4. 计算推荐结果列表#### cal.mr<-mapreduce( input=eq.hdfs,#eq.hdfs的key=NULL,value为: item1 item2 frequency item=item1 user pref map=function(k,v){ val<-v#value na<-is.na(v$user.r)#user if(length(which(na))>0) val<-v[-which(is.na(v$user.r)),]#剔除缺失ID的用户 keyval(val$k.l,val)#key为item1,value为:item1 item2 frequency item=item1 user pref } ,reduce=function(k,v){ val<-ddply(v,.(k.l,v.l,user.r),summarize,v=freq.l*pref.r) keyval(val$k.l,val)#key为item1,value为:item1 item2 user 推荐结果 } ) from.dfs(cal.mr)#key为item1,value为:item1 item2 user 推荐结果 ####5. 按输入格式得到推荐评分列表#### result.mr<-mapreduce( input=cal.mr,#key为item1,value为:item1 item2 user 推荐结果 map=function(k,v){ keyval(v$user.r,v)#key为user,value:item1 item2 user 推荐结果 } ,reduce=function(k,v){ val<-ddply(v,.(user.r,v.l),summarize,v=sum(v)) val2<-val[order(val$v,decreasing=TRUE),]#对推荐结果排序 names(val2)<-c("user","item","pref") keyval(val2$user,val2) } ) from.dfs(result.mr)#key为user,value:user item pref