查看原文
其他

R下如何实现VLOOKUP函数功能

2017-03-14 kaolixin R语言中文社区

缘起:

当我怀着对周末生活的美好憧憬等待下班的时候,突然领导拿着N份Excel表要求将上面的数据按月汇总到另一张Excel表中(汇总表格如题图)。也许领导也知道工作量不小,临走时留一下句:“辛苦一下,加加班,周一给我!”嘴上机械的回道:“好的”,心里羊驼狂奔,脑中各种处理方法快速闪过,最后定格在“VLOOKUP函数”。作为Excel中最强大的函数之一 ,vlookup果然不负重望,完美地汇总了数据,关键保住准时下班。


我的问题 Excel的vlookup那么强大,在R中能实现嘛?

我的尝试 在《R语言实战》的第四章-4.9.1 添加列(P76)提到 merge() 函数可以根据一个或多个共有变量把两个数据框联结起来。可是实践结果(如下图)告诉我,merge()函数是行不通的。因为两个数据框中变量Month的观测量不一致,所以联结的结果以观测量少的数据框准把部分Month丢掉了。



有问题找谷哥,关键词:how to vlookup in r


很给力,第一个结果就给出了四种解决方案


但很遗憾,似乎R中的“Vlookup()函数”就是merge()函数,难道共有变量的观测数就一定要相同嘛?在反复阅读搜索结果后,发现了特别说明,找到了希望:


sqldf()效果还不错,Month都留下了(如下图),但NA怎么处理呢?Excel中Ctrl+H,可以轻松用任意字符把NA 替换掉


量重编码)可以实现NA替换为“0”。

实践进阶 既然myframesqldf[2][is.na(myframesqldf[2])] <-"0"可以对满足条件的某个观测值进行斌值,那么是不是也可以通过两个数据框Month的值是否相等来对le进行斌值呢?



结果并不理想,与sqldf()做出的完全不同。什么原因呢?是两个数据框的共有变量的观测数不一致嘛??还是两个向量不能直接进行比较呢?或者说两个向量的运算规则是什么样的?用paste()函数做一下实验(《R语言实战》P90)


不难看出,两个向量的运算是可以进行比较等运算的,但其运算规则并不是我之前想象那样,某个向量的每一个观测与另一个向量的每一个观测进行运算,而是以观测数大的向量为线索,观测数小的向量按自身顺序循环进行运算。为了实现某个向量的每一个观测与另一个向量的每一个观测进行运算,我想到了for()函数。


结果和Excle的VLookup完全一致。


我的代码:

##待汇总数据准备
zs <- data.frame(Month=as.character(c("一月","四月","五月")),income=as.numeric(c(352,778,992)),stringsAsFactors = FALSE)
ls<- data.frame(Month=as.character(c("二月","五月","七月")),income=as.numeric(c(457,787,199)),stringsAsFactors = FALSE)
ww<- data.frame(Month=as.character(c("一月","五月","六月","七月")),income=as.numeric(c(457,787,287,277)),stringsAsFactors = FALSE)
cy <-data.frame(Month=as.character(c("五月","六月","七月")),income=as.numeric(c(787,287,277)),stringsAsFactors = FALSE)
le <-data.frame(Month=as.character(c("二月","五月","六月")),income=as.numeric(c(777,387,777)),stringsAsFactors = FALSE)
tb <- data.frame(Month=as.character(c("五月","六月","七月")),income=as.numeric(c(787,287,277)),stringsAsFactors = FALSE)
Month <- c("一月","二月","三月","四月","五月","六月","七月")
myframe <- data.frame(Month=as.character(Month),zs="0",ls="0",ww="0",cy="0",le="0",tb="0",stringsAsFactors = FALSE)

#sqldf包法 ps: install.packages("sqldf")
library(sqldf)
data.frame(Month=as.character(Month),stringsAsFactors = FALSE)
myframe1 <- sqldf("select * from myframe left join le using (Month)")
names(myframe1)[2] <- "le"
myframesqldf[2][is.na(myframesqldf[2])] <-"0"
##双for()函数法
for(i in 1:length(zs$Month)){for(j in 1:length(myframe$Month)){if(myframe$Month[j]==zs$Month[i])myframe$zs[j] <- zs$income[i] }}
for(i in 1:length(ls$Month)){for(j in 1:length(myframe$Month)){if(myframe$Month[j]==ls$Month[i])myframe$ls[j] <- ls$income[i] }}
for(i in 1:length(ls$Month)){for(j in 1:length(myframe$Month)){if(myframe$Month[j]==ww$Month[i])myframe$ww[j] <- ww$income[i] }}
for(i in 1:length(ls$Month)){for(j in 1:length(myframe$Month)){if(myframe$Month[j]==cy$Month[i])myframe$cy[j] <- cy$income[i] }}
for(i in 1:length(ls$Month)){for(j in 1:length(myframe$Month)){if(myframe$Month[j]==le$Month[i])myframe$le[j] <- le$income[i] }}
for(i in 1:length(ls$Month)){for(j in 1:length(myframe$Month)){if(myframe$Month[j]==tb$Month[i])myframe$tb[j] <- tb$income[i] }}
##单for()函数法
for(i in 1:length(zs$Month)){myframe$zs[myframe$Month==zs$Month[i]] <- zs$income[i]}
for(i in 1:length(ls$Month)){myframe$ls[myframe$Month==ls$Month[i]] <- ls$income[i]}
for(i in 1:length(ww$Month)){myframe$ww[myframe$Month==ww$Month[i]] <- ww$income[i]}
for(i in 1:length(cy$Month)){myframe$cy[myframe$Month==cy$Month[i]] <- cy$income[i]}
for(i in 1:length(le$Month)){myframe$le[myframe$Month==le$Month[i]] <- le$income[i]}
for(i in 1:length(tb$Month)){myframe$tb[myframe$Month==tb$Month[i]] <- tb$income[i]}

感谢:

谢谢您花时间读到这里,尤其是作出评论的亲。数据分析学习之路,有您真好!


kaolixin,天善智能社区专家。

Blog:https://ask.hellobi.com/blog/kaolixin


微课推荐:(阅读原文报名)

您可能也对以下帖子感兴趣

文章有问题?点此查看未经处理的缓存