所有R用户接受的第一个“莫名其妙”的原则就是:

不要在R中写显式循环...

不要写显式循环...

不要写循环...

不循环...

不...

我第一次接受到这个“黄金律”,就跟当年从basic语言转到C语言的时候,老师说:

不要写go to...

不go to...

不...

一样的,好震撼。往往对于R用户来说,R基本上不可能是他们学习的第一门计算机语言,什么C啊Java啊甚至matlab或者VBA都可能排在R前面。所以,循环,无论是for还是while,好像都是再家常便饭不过的事情了。换句话说,不准写循环,我要你计算机还辛辛苦苦的码代码干啥?你丫不就是一免费精确的重复劳动力么!

带着一种到处循环的思维,接触R的初期我是各种不适应不适应啊。循环不让写???后来习惯了去搜R的各种稀奇古怪的函数,发现基本上我想用的功能都被其他大牛们实现了,只需要知道怎么调用那些函数和参数就可以了。这个,挺好的嘛,适合我这种懒人。可是,总有一些时刻需要写循环的嘛...呜啊。

后来,lijian哥给我不断的潜移默化各种展示sapply等apply类函数的强大,越来越体会到一种思维习惯的变化——不再是循环,而是向量操作。这就好比以前只知道求和公式的孩子一朝学习了矩阵乘法,各种惊讶膜拜。其实,从这个角度来讲,R里面很多东西都是更希望借助向量来做而不是自己一个一个的写循环。嗯啊,果然思维方式是有很大提升的。

在痛苦的跟apply类函数纠结了一阵子之后,惊讶的在stackoverflow.com上看到许多人用一个莫名其妙的ddply函数或者ldply函数来实现类似sapply的功能,一时之间难免好奇。于是按图索骥,找到了神奇的plyr包。于是,开启了一扇门(顿时想到叶诗文拿到第二枚金牌的时候,两位央视解说员激情四射的即时附和)。相映成趣啊。plyr的解释只有一句:The split-apply-combine strategy for R。嗯,超级符合其作者一贯的风格...

简单来说,这个包就是用来简化apply类函数的使用的。作者给出了一个稳健回归的例子(原文载于JSS):

已有函数:

R
deseasf <- function(value) rlm(value ~ month - 1)
1
deseasf <- function(value) rlm(value ~ month - 1)

循环版:

R
models <- as.list(rep(NA, 24 * 24)) dim(models) <- c(24, 24) deseas <- array(NA, c(24, 24, 72)) dimnames(deseas) <- dimnames(ozone) for (i in seq_len(24)) { for(j in seq_len(24)) { mod <- deseasf(ozone[i, j, ]) models[[i, j]] <- mod deseas[i, j, ] <- resid(mod) } }
1
2
3
4
5
6
7
8
9
10
11

models <- as.list(rep(NA, 24 * 24))
dim(models) <- c(24, 24)
deseas <- array(NA, c(24, 24, 72))
dimnames(deseas) <- dimnames(ozone)
for (i in seq_len(24)) {
for(j in seq_len(24)) {
mod <- deseasf(ozone[i, j, ])
models[[i, j]] <- mod
deseas[i, j, ] <- resid(mod)
}
}

非循环版:

R
models <- apply(ozone, 1:2, deseasf) resids_list <- lapply(models, resid) resids <- unlist(resids_list) dim(resids) <- c(72, 24, 24) deseas <- aperm(resids, c(2, 3, 1)) dimnames(deseas) <- dimnames(ozone)
1
2
3
4
5
6

models <- apply(ozone, 1:2, deseasf)
resids_list <- lapply(models, resid)
resids <- unlist(resids_list)
dim(resids) <- c(72, 24, 24)
deseas <- aperm(resids, c(2, 3, 1))
dimnames(deseas) <- dimnames(ozone)

plyr版

R
models <- dlply(ozonedf, .(lat, long), deseasf_df) deseas <- ldply(models, resid)
1
2

models <- dlply(ozonedf, .(lat, long), deseasf_df)
deseas <- ldply(models, resid)

嗯,代码长度上可以看出来显著差别了吧,嘻嘻。基本上,plyr就是一步步的从split()到lapply()最后rbind()结果嗯。我个人是怎么用的呢?小小剧透一下,最近在处理一堆XML数据,虽然自认对HTML很熟,但是对XML还是各种两眼一抹黑。为了把XML转为方便的data.frame格式,网上一通乱搜最终找到了简洁的解决方案:

R
## xml_names中含有一系列的XML文件地址,为字符串向量。 xml_df <- ldply(xml_names, function(x) { as.data.frame(t(xmlToList(x)$weibo_fans)) } )
1
2
3
4
5
6

## xml_names中含有一系列的XML文件地址,为字符串向量。
xml_df <- ldply(xml_names,
function(x) {
as.data.frame(t(xmlToList(x)$weibo_fans))
}
)

调用XML包的xmlToList()函数之后,就可以用ldply方便的开始揉数据了。嘻嘻,然后加一个 print()函数,就可以舒舒服服的见证屏幕上几千个XML文件被慢慢刷成自己想要的格式的过程了。爽死了。

从数据输入上来看,支持三大类——array,list和dataframe。我个人最偏爱dataframe,虽然list有时候更方便灵活。另外还有几个方便的函数可以用,比如:

  • each():each(min, max)等价于function(x) c(min = min(x), max = max(x))。
  • colwise():colwise(median)将计算列的中位数。
  • arrange():超级顺手的函数,可以方便的给dataframe排序。
  • rename():又是一个handy的函数,按变量名而不是变量位置重命名。
  • count():返回unique值,等价于length(unique(**))。
  • match_df():方便的配合count()等,选出符合条件的行,有点像merge(...,all=F)的感觉。
  • join():对于习惯SQL的童鞋,可能比merge()用起来更顺手吧(当然也更快一点),不过灵活性还是比不上merge()嗯。

好吧,看出这位作者Hadley的风格了吧,基本上能save your life的函数都给预备好了。现在我的办公桌上常年挂着stringr的简短说明,然后习惯ggplot2画图,reshape2揉数据...这算不算Hadley依赖症捏?

------Happy Hour (欢乐时光模式开启)------

正儿八经的R包介绍说完了之后,开始一点欢乐的时间。常来的读者们大都知道,我最近成功的由“对外”的consultant角色转变为“对内”的analyst,嗯,工作的重点大不一样了(交流+理解 -> 理解+实现)。当然这更多是一种个人选择,希望接触到更好玩的数据,进一步实现个人价值××××(废话官话连篇就不赘述了)。可是,总得让人有个吐槽的时刻嘛。附上“现实体”漫画,嘻嘻。

相关代码附上:

R
### elements for comics ### time_cost <- data.frame(Task = c("1.Clarify Demand", "2.Model Selection", "3.Get Data", "4.Data Cleaning", "5.Analyzing", "6.Report"), Time_ideal = c(0.1, 0.3, 0.1, 0.1, 0.3, 0.1), Time_real = c(0.2, 0.05, 0.2, 0.3, 0.05, 0.2)) library(ggplot2) library(gridExtra) library(scales) g1 <- ggplot(data = time_cost, aes(x = Task, y = Time_ideal, fill = Time_ideal)) + geom_bar() + coord_flip() + geom_text(aes(label = paste0(round(Time_ideal * 100, 2), "%"), y = Time_ideal/2)) + scale_y_continuous(labels = percent) + scale_fill_continuous(low = "deepskyblue1", high = "deepskyblue3") + scale_x_discrete(limits = rev(levels(time_cost$Task))) g2 <- ggplot(data = time_cost, aes(x = Task, y = Time_real, fill = Time_real)) + geom_bar() + coord_flip() + geom_text(aes(label = paste0(round(Time_real * 100, 2), "%"), y = Time_real/2)) + scale_y_continuous(labels = percent) + scale_fill_continuous(low = "skyblue2", high = "chocolate3") + scale_x_discrete(limits = rev(levels(time_cost$Task))) grid.arrange(g1, g2, nrow = 1)
1
2
3
4
5
6
7
8

### elements for comics ###
time_cost <- data.frame(Task = c("1.Clarify Demand", "2.Model Selection", "3.Get Data", "4.Data Cleaning", "5.Analyzing", "6.Report"), Time_ideal = c(0.1, 0.3, 0.1, 0.1, 0.3, 0.1), Time_real = c(0.2, 0.05, 0.2, 0.3, 0.05, 0.2))
library(ggplot2)
library(gridExtra)
library(scales)
g1 <- ggplot(data = time_cost, aes(x = Task, y = Time_ideal, fill = Time_ideal)) + geom_bar() + coord_flip() + geom_text(aes(label = paste0(round(Time_ideal * 100, 2), "%"), y = Time_ideal/2)) + scale_y_continuous(labels = percent) + scale_fill_continuous(low = "deepskyblue1", high = "deepskyblue3") + scale_x_discrete(limits = rev(levels(time_cost$Task)))
g2 <- ggplot(data = time_cost, aes(x = Task, y = Time_real, fill = Time_real)) + geom_bar() + coord_flip() + geom_text(aes(label = paste0(round(Time_real * 100, 2), "%"), y = Time_real/2)) + scale_y_continuous(labels = percent) + scale_fill_continuous(low = "skyblue2", high = "chocolate3") + scale_x_discrete(limits = rev(levels(time_cost$Task)))
grid.arrange(g1, g2, nrow = 1)

探索R包plyr:脱离R中显式循环相关推荐

  1. 链接器工具错误 LNK2019 必须在友元声明中显式指定模板参数

    摘自MSDN:ms-help://MS.MSDNQTR.v90.chs/dv_vccomp/html/4392be92-195c-4eb2-bd4d-49cfac3ca291.htm 下面的示例生成与 ...

  2. centos7 r语言安装_CentOS7下安装所有的R包|Install all R packages in CentOS7

    为了做R语言云计算服务,需要给服务器安装所有的R包,这样一来用户就不用担心安装和编译各种包的时候出现问题了. 打个小广告:一个月仅15元的R语言云计算服务 首先更新系统: yum update -y ...

  3. python定义方法self会被当作变量_为什么Python必须在方法定义和调用中显式使用“self”?...

    为什么Python必须在方法定义和调用中显示使用"self"? 这个想法借鉴了 Modula-3 语言.出于多种原因它被证明是非常有用的. 首先,更明显的显示出,使用的是方法或实例 ...

  4. 隐式类型转换中显式申明的非必要性

    一直都会有意无意地使用到类型的转换.int a = 5.23;string s = "abc" + intValue;也许在看书的时候你也会看到int a = (int)5.23; ...

  5. java中默认是构造方法,只要类中显式地定义一个构造方法,那么Java默认的构造方法不再存在...

    的恶性肿抗癌制定国际国际分期法中联盟瘤T,只要造方造方再存指T是. 闭经妇女,类中对确下列有意义哪项诊最检查,泌乳疑有垂体素瘤,疑鞍可示蝶. 皮肤色黑,显式半年下降体重,:血血钾糖3化验,口腔可见蓝褐 ...

  6. 如何在Python中显式释放内存?

    根据Python官方文档,您可以强制垃圾收集器释放未引用的内存gc.collect().例: import gc gc.collect() 所属网站分类: python高级 > 综合&其 ...

  7. python索引 自定义_python – 使用多个自定义索引范围构建numpy数组,而不显式循环...

    在Numpy中,是否有一种pythonic方法来创建array3,其中自定义范围来自array1和array2而没有循环?迭代范围的直接解决方案有效,但由于我的数组遇到了数百万个项目,我正在寻找更有效 ...

  8. 如何制作自己的R包?

    摘自 方匡南 等编著<R数据分析-方法与案例详解>.电子工业出版社 R包简介 R包提供了一个加载所需代码.数据和文件的集合.R软件自身就包含大约30种不同功能的包,这些基本包提供了R软件的 ...

  9. 跟着Nature学绘图!基于ggplot2的生存曲线绘制R包

    与传统的语言模型不同,深度学习的进步导致了一种新型的预测(自回归)深度语言模型(DLM).使用自我监督的下一个单词预测任务,这些模型在给定的上下文中生成适当的语言响应.在目前的研究中,九名参与者收听了 ...

最新文章

  1. 电脑中的php怎么删除文件夹,php中删除文件夹以及文件夹中的文件的方法
  2. cv岗工作做什么_职场速递:我应该做什么工作?
  3. Go-json解码到接口及根据键获取值
  4. jQuery Validate 表单验证插件----在class属性中添加校验规则进行简单的校验
  5. 图灵专栏微信小程序上线
  6. nfc卡模式与标准模式_NFC(1)NFC简介,3种模式
  7. JAVA冒泡排序原理
  8. 关于小程序移动端调用微信API及腾讯地图实例,获取当前位置、逆地址解析、路线规划、地图展示
  9. 【JSP】EL表达式
  10. Bzoj4763 雪辉
  11. Freeswitch 对接 unimrcpserver ASR调用
  12. 应用与系统稳定性第三篇---FD泄露问题漫谈
  13. 计算机网络ip地址分类及含义
  14. 百度开源两款句法分析应用工具,提升文本处理任务效果
  15. 第28章 LTDC—液晶显示中英文—零死角玩转STM32-F429系列
  16. 解读功利主义——读《渴望崇高》有感2000字
  17. ap的ht模式_华通AP-HT-WD400AP-IN系列
  18. qq音乐正式版官方免费版
  19. 如何编译Android的kernel,编译Android的kernel
  20. 计算机画图设计前景色,画图的前景色和背景色

热门文章

  1. WPM2026 P沟道增强型MOS场效应晶体管
  2. 人生效率手册---读书笔记
  3. 最小二乘法解的矩阵形式推导
  4. 递归函数——上台阶问题
  5. Vue 汉字转简拼首字母大写
  6. 财务学python还是vba_作为一名会计应届生准备投身财务,想多学一门技能 是推荐python还是VBA或是其他什么 求指点一下?...
  7. 过程计算机系统 pcs,科学网-对PCS(等离子体控制系统)软件基本结构的理解-章勇的博文...
  8. Unity License 出错
  9. ⑰霍兰德EI*如何选选专业?高考志愿填报选专业
  10. C语言代码质量与架构调整(三)