作为半个码农,有两次程序侦察工作窃以为得意。一次是统计之都网站改版时的豆腐块对齐工作,这已经说过了;另一次是今天琢磨LyX与Sweave的时候,又碰到一个非常隐蔽的问题,但还是把它揪了出来。
论坛上一次又一次有人抱怨Sweave中使用中文的问题,而这也是我自己写书必须要用的工具,所以在这里面投入了不少精力。过去我一直用得好好的,昨天突然发现我的也用不了中文了,相当郁闷。注意到从LyX里面启动R的时候有这么一项警告:
13:30:28.553: /bin/bash: warning: setlocale: LC_ALL: cannot change locale (en_US) 13:30:28.624: During startup - Warning messages: 13:30:28.625: 1: Setting LC_CTYPE failed, using "C" 13:30:28.626: 2: Setting LC_COLLATE failed, using "C" 13:30:28.626: 3: Setting LC_TIME failed, using "C" 13:30:28.626: 4: Setting LC_MESSAGES failed, using "C" 13:30:28.627: 5: Setting LC_PAPER failed, using "C" 13:30:28.627: 6: Setting LC_MEASUREMENT failed, using "C"
后面接着有警告说某些字符无效,显然这是编码或区域设置(locale)的问题了:Sweave无法正常读写文档。因为最近R曾经升级过,而我的LyX也一直用的源代码编译版,所以麻烦就在于不知道到底是谁的问题(昨天看樱桃小丸子,发现连丸尾都懂得confounding的道理,当时就震惊了)。
捣鼓了半天编码设置,如options('encoding')之类的,发现无效。我的locale应该是en_US.UTF8才对,到底是谁把它弄成en_US了呢?幸好英文文档还可以正常编译,于是在Sweave中插入一句as.list(Sys.getenv())看看所有的环境变量,发现环境变量LC_ALL很可疑。于是怀疑LyX修改了这个变量,正常的R启动之后LC_ALL是空字符串。那么LyX在哪里修改的?试着把LyX的语言修改为默认语言,再跑一遍LyX/Sweave,发现LC_ALL正常了,变成了空字符串,中文文档也可以正常读写了。真相大白——(暂时)不要人工设置LyX的语言。这可能是一个bug,我一边报告,一边自己找到了临时解决办法。
环境变量就是恶魔啊。比如PATH就是码农最需要但又最痛恨的环境变量之一,痛恨它主要是因为(至少对我来说原因是)在Windows下得走很远才能找到它,常常让人没有耐心向不懂的人解释,而大多数人可能这辈子也不会意识到系统中有这些小恶魔的存在。
回到LyX与Sweave:因为重头开发者度假去了,所以恐怕对Sweave的完美支持在近两个月内又不太可能了。
这是旧闻了。只不过我这两天在埋头苦改其中的Sweave部分,刚刚改得差不多了,发了个大大的SVN补丁过去。可惜没能赶在2.0之前搞定。pgfSweave也作为单独的模块加进去了,有超级牛力。不知能否赶上2.0.1的趟,也不知2.0.1啥时侯发布。
总之以后不用费劲折腾了,配置啥的都将变得很简单。
R 2.13.0今日出炉,一大批更新中有以下条目吸引了我的眼球:
- image() has gained a logical useRaster argument allowing it to use a bitmap raster for plotting a regular grid instead of polygons. This can be more efficient, but may not be supported by all devices. The default is FALSE.
不知道tikzDevice能否正确处理,如果可以的话,也许可以放心使用image()了,之前由于tikz生成的image()的图形既大(因为是很多矩形)又有难看的白色网格,所以让我一直很纠结。 - file.copy() now (by default) copies read/write/execute permissions on files, moderated by the current setting of Sys.umask().
这个问题貌似是我报告过的,因为roxygen拷贝configure文件的时候会把744属性丢失。 - New hook “before.new.plot” allows functions to be run just before advancing the frame in plot.new, which is potentially useful for custom figure layout implementations.
这让我们可以在.Rprofile文件中设定默认的par(),免得每幅图都要par()来par()去的。 - Package tools has a new function compactPDF() to try to reduce the size of PDF files _via_ qpdf or gs.
这qpdf貌似也是我推荐的,主要是因为Sweave默认用PDF图形,而这些PDF图形都是没有经过压缩的,所以导致包的体积不必要地大。 - file.rename() now allows vector arguments (of the same length).
省去了循环。 - Package compiler is now provided as a standard package. See ?compiler::compile for information on how to use the compiler. This package implements a byte code compiler for R: by default the compiler is not used in this release. See the ‘R Installation and Administration Manual’ for how to compile the base and recommended packages.
也许有人在Google Reader中看到了我的分享,这是Luke Tierney十几年的工作,终于浮出了水面,此举也许能让R的运算速度加快几倍。如果自己通过make install的方式安装,可以先make bytecode,回头测试一下速度。 - Sweave() has options to produce PNG and JPEG figures, and to use a custom function to open a graphics device (see ?RweaveLatex).
(Based in part on the contribution of PR#14418.)
这是我们抱怨了无数遍的一点:Sweave不能使用除了PDF和Postscript之外的图形。在2.14.0中这个问题将进一步得到解决,到时候可以任意自定义图形设备。 - The default for Sweave() is to produce only PDF figures (rather than both EPS and PDF).
我早说了,这年头有谁还会用老旧的EPS图形啊?2.14.0的时候,一段Sweave代码只会被执行一遍,这也是我期待很久的特征。 - If there is a field BuildVignettes in the package DESCRIPTION file with a false value, re-building the vignettes is skipped.
此举可节省R包安装时间,尤其是有大的vignette或者其中有CRAN的环境无法编译的代码。 - File R.css is now installed on a per-package basis (in the package’s html directory) rather than in each library tree, and this is used for all the HTML pages in the package. This helps when installing packages with static HTML pages for use on a webserver. It will also allow future versions of R to use different stylesheets for the packages they install.
同样是抱怨过的问题,R默认的css太丑了,现在包的开发者终于可以自定义R.css了。 - The gamma argument to hsv(), rainbow(), and rgb2hsv() is deprecated and no longer has any effect.
对我写书有一点小影响,不过我早已经更新这些函数在书中的说明。
总的说来,还是compiler包看起来是最大的更新。
转眼间LyX 2.0已经陆续发布beta 1, 2, 3, 4,希望不要再发beta 5,直接出正式版吧。这回在LyX 2.0中Sweave有了内生支持,不过它自带的Sweave的缺点一大堆,前天上午本来想给LyX报告一下这些事情,结果写着写着,自个儿发现了解决办法,昏死,写了几大段道理,白写了。抄起键盘给2.0写了个Sweave自动配置脚本,仅仅在Ubuntu下测试了一下,貌似还挺好使。勇猛的Linux用户可以自行下载LyX 2.0 beta4源代码包编译安装,然后在R里运行:
source('http://gitorious.org/yihui/lyx-sweave/blobs/raw/lyx2/lyx-sweave-config.R')
示例文件:http://gitorious.org/yihui/lyx-sweave/blobs/raw/lyx2/demo/pgfSweave-in-LyX-2.0.lyx
关键之处在于,Sweave从此变成了LyX的一个模块(module),对LyX了解的人都知道这样做的意义:它意味着你可以对任意文档应用Sweave,从此脱离了layout的限制。只要一个文档应用了pgfSweave这个模块,那么LyX就会认为这是个文学编程文档,从而调用R去执行文档中的代码生成LaTeX。这是最显著的进步。
其次,我以前提过,LyX/Sweave文档中的R代码中如果使用回车换行,那么得到的结果是代码之间会产生空行。这也是让人很不爽的一点,在2.0中也已经由ParbreakIsNewline标签解决了。这将增强格式化R代码的功能,用户可以用keep.source = TRUE来保留自己的代码格式而不必担心空行的问题。
LyX 2.0另一个牛哄哄的地方在于它终于能显示debug的信息了,这让我们可以省下不少力气去研究什么命令行重定向之类的玩意儿:直接勾上LyX菜单View –> View Messages,就可以看到整个编译的过程了,包括R里面的进度,都一清二楚,哪个代码段要是出错了立马就能知道。这给查错带来了无穷的便利。
总结一句话:牛可牛,非常牛。
近段时间发现Ubuntu下编LaTeX似乎比Windows下快很多,尤其是动画,Windows下每一页图都要编上一两秒,整个动画编出来黄花菜都凉了。另外发现animate宏包实际上已经能和\def\input@path一起用,所以动画文件不必写绝对路径,在LyX中就可以用了。只可惜Ubuntu中的TeXLive更新实在是太慢太慢,让我花了很长时间才意识到animate已经更新了,我的问题已经解决了;我对Ubuntu中最不满的一个软件就是TeXLive,它的宏包管理功能比MiKTeX差太远太远了。现在MiKTeX有个简单的Linux版本的宏包管理器,算是可以凑合着用吧(从源代码编译会出错,不过Google一下就解决了)。
圣诞节上传了animation v1.1-5到CRAN FTP,不过估计管理员都度假去了,要等一阵子才能放出来了。这次更新主要有两个变化:一是增加了命名空间(NAMESPACE),这玩意儿是我以前没太搞明白的东西,现在明白它的优势了(控制哪些对象是对用户可见的);二是把saveLatex()函数大幅度改写了一下,尤其是用“黑魔法”让它能自动应付Sweave,如果它探测到自己是在Sweave环境中,那么会自动根据代码段的标签和前缀生成动画文件并插入LaTeX文档,而且有选项overwrite = TRUE/FALSE控制是否重画动画(可以看作是最初级的“缓存”方法)。从此以后,在Sweave文档中动态生成动画就方便了,如此一来,也算不辜负这个包被收录在ReproducibleResearch的CRAN Task View中。至于怎么在Sweave中生成动画,若有人感兴趣,我也可以下次在统计之都主站上介绍一下,这东西应该对一些人有用。
我一直在找如何在Git中永久删除某些文件(包括它们的历史记录)的办法,这个问题也是花费我时间最多的一个Git问题,所幸最后终于在GitHub的帮助页面“Removing sensitive data”中找到了答案。尽管我并不完全明白工作原理,但好歹这个办法管用了:
## 注意Windows下用双引号 git filter-branch --index-filter 'git rm -r --cached --ignore-unmatch path/to/your/file' HEAD git push origin master --force rm -rf .git/refs/original/ git reflog expire --expire=now --all git gc --prune=now git gc --aggressive --prune=now
当时从SVN迁到Git的时候犯了个错误:把整个库都迁过来了(我应该只迁一个子目录),但实际上很多文件都是我不想放到这边来的,比如那些二进制图片文件。它们让整个库的体积增大了太多,而版本控制工具的特点就是记录你对文件的所有操作,包括删除,即使在当前版本中删除了,Git也会在历史记录中记下这些文件,以便随时可以恢复回去。对于这些几十兆的大文件我一直“耿耿于怀”,现在GitHub上的库终于轻松了,大小只有1M了。
LyX 2.0的layout文件中将正式引进一个新标签ParbreakIsNewline,它让我过去的一个工作变成了废物,即:如何在代码块中回车换行,而不是Ctrl回车来换行。这种事情还是靠开发者从源头上解决比较好,民间技巧毕竟不是长久之计。
Sweave支持一个\SweaveInput{}命令,话说我用了这么久,完全没有意识到有这么个东西的存在。今天偶然发现,还是从LyX 2.0的sweave.module中看到的。Google之,无文档无说明。气煞我,我老早就在琢磨是否能将Sweave文档像LaTeX那样用\include{}分成几个小文档,原来这东西早就存在了。然后,又是不理解,为什么Leisch老大设计Sweave的时候总是喜欢发明一些新命令,你去解析\include{}命令不是挺好的么,干嘛又发明一个\SweaveInput{}。就像\Sexpr{}和\SweaveOpts{}一样,都是些伪LaTeX命令,我总觉得不优雅。
看了一下LyX的InsertLayout的用法,挺好的,早该看而没看的东西。
因为想写个包的文档,所以又回头看了看上次写的自动配置LyX和Sweave的脚本,左看右看觉得死板,于是乎又花了一天时间改写了一下。现在萝卜青菜,愿意吃啥吃啥了,把R执行的部分抽象出来单独放在一个文件中,如果将来想做新的配置,只需要在外部改这个R代码就可以了,从LyX彻底独立了出来。
source('http://gitorious.org/yihui/lyx-sweave/blobs/raw/master/lyx-sweave-config.R')
命令行环境的细节真是能淹死人,今天才知道原来Windows的命令行窗口中,尖尖符号^是转义符;不懂它为啥要特立独行,人家都用反斜杠\转义。
现在的工作基本上全面转向Git;各大支持Git的网站中,可能GitHub是最好用的,大大提高了程序开发效率。尤其是其代码行内评论的功能,很是方便交流。有了前面介绍的Rd2roxygen包之后,开发R包也轻松多了,基本上就是在Emacs里C-c C-o,完事之后终端打开R,运行一下两句代码的事情:
library(Rd2roxygen)
rab('your.pkg')
现在再加上LyX/Sweave这把刀也磨好了,于是写Vignette也不在话下。人挡杀人,佛挡杀佛。最终有了勇气把那些塞到犄角旮旯的老R包都捡出来,继续开发。上周animation和formatR分别更新了新版本;Rd2roxygen也放了新版本(为了更加懒惰);老早以前的那个fun包也复活过来,再把文档整理一下,大概也是可以正式发布的。怡轩还翻出了另一个老想法:在R中原生支持生成Flash动画。现在已经完成了从PNG图形到SWF的转换,所有结果都在一个新包R2SWF中(将来也许会合并到animation中)。
外一篇:羊群效应
最近两天COS论坛上出现了一个典型的羊群效应:某一只新“羊”发帖以“急”开头,后来得到了回答,该羊可能便认为“急”是有用的,于是就每个帖子都来“急”一下;后来又来了一只羊,发帖以“ASAP”(越快越好)结尾,后来得到了回答,于是该羊也不假思索发帖一律加上ASAP结尾;又来了些新羊,大家看前面都是急帖,于是都跟着急。整个论坛就这样急起来了。有好事者问了一下其中一只羊,为啥要ASAP呢,结果发现事实不是ASAP。本来我就对急帖心存反感,一问还不是真的急(就像听了个狼来了的故事),这以后旁观者到底还该不该急呢?
我来说个高级一点的“浮云”:很久以来我都很不满Sweave的错误处理机制,甚至都有改写Sweave源代码的念头,这件事情本应该很容易解决,但R core们估计太忙了——每段代码加上try()然后要是出错就打印错误信息,不要让Sweave直接在某段代码上挂掉。最近R 2.12.0在这个问题上改进了一小步,如果代码段解析出错,那么会打印错误出现的行号,但还是没解决根本问题,后面据说还要改进。这是引子。
Sweave出错就让R挂掉这种方式对于用LyX来说非常不方便,每当出错,都很难查错,因为没有任何错误日志;要检查错误,还得打开R,在交互模式下运行Sweave(),看到底哪里错了。这也是很久以来我觉得头疼的问题。这学期做579课的TA,上周两节课讲LyX和Sweave,因为我一直鼓吹LyX的种种好处,二老板估计也好奇,于是就把课交给我来上。这LyX+Sweave好用是好用,就是配置过程太琐碎,上课花了不少时间在这个配置上,于是课下花了很大功夫写了个自动配置脚本,尽量让用户不必管任何细节问题,一切都用命令行搞定。然而还是没有错误信息的解决办法,学生们的文档运行出错我通过Email也很难知道错在哪里,很多时候只能凭经验。
今天应开(这是个人名)同学也问起这个问题,我回复了我的查错办法之后他回了他的办法:调用R的时候,将命令行输出重定向到文件就可以了,也就是这种形式:
R -e Sweave('your-Sweave-file.Rnw') >> your-log-file.log
原来答案这么简单,我怎么没想到呢。
小月月那点浮云算啥浮云呐,这才真的叫“神马都是浮云”。
陈丽云这篇博客“真的是只大狐狸吗?对江西财经陈军昌博士的探究”让我想起一个长期以来我关心的一个话题。我对陈军昌这个人本身不如我对他的摘要的兴趣大,此君提到:
本文预言:在不久的未来,计算机技术将会借助非线性问题的进展彻底占据经济学的主流地位。这项技术不再是简单的用于经验数据的回归预测,而将成为主流形式化逻辑。 本文作者甚至计划在将来使用纯计算机程序的形式化逻辑写作一篇经济学论文。
我完全相信这段预言。倒不是说我觉得这种做法是对的,只是在目前可见的范围内,我严重怀疑堆积如山的经济学论文是否还需要人的脑子,我甚至想象,给一个Sweave模板,提供几个参数(如欲选择用什么模型、生成什么样式的图形),然后把数据读进来用R跑一遍,一篇论文就自动生成了,加上LaTeX本身就显得正式,这种论文一定人模狗样的,很能忽悠人。比如:
\Sexpr{names(dat)[1]}的均值为\Sexpr{mean(dat[ ,1])},标准差为 xxx。图\ref{...}为\Sexpr{figname[1]}:……
\Sexpr{modname[1]}模型显示,斜率项为\Sexpr{coef(dat.lm)[2]}(t 检验结果为\Sexpr{ifelse{coef(summary(dat.lm))[2,4]<0.05, '显著', '不显著'}})。
把目前主流杂志上的经济学论文遍历一下,总结一个八股规则,生成统计分析部分。至于结尾嘛,就把所有论文的结论部分分条存在一个数据库中,随机抽取5条就可以了,反正大家的结论都很NB,都对社会主义建设有重大意义。
调侃归调侃。如果这位陈博士的论文真的能被广为接受的话,我估摸着将来大多数期刊是不是要去喝西北风了。以上是经济学界的事情,与我没啥关系,暂不多说。还是回头说统计。
我不确定这是不是R和Sweave能达到的最漂亮的境界:
下载:一份由pgfSweave生成的人模狗样的动态文档这两天花了点时间,把跟LaTeX、LyX、Sweave有关的一系列中文问题从头到脚翻了个遍,目前为止,明白并解决了如下问题(基于带有MikTeX 2.8的CTeX 2.8.0.125、LyX 1.6.5、R 2.10.1、R包pgfSweave 1.0.3,操作系统Win XP,从头到尾一直用UTF-8编码):
- (LaTeX说中文了)LaTeX生成可复制粘贴的中文PDF文档:由于我的惰性,还用着N年前的CTeX,那个老版本CTeX中的MikTeX貌似一直有问题,比如无法更新LaTeX宏包,更不必说那些
dvipdfmx之类的程序了,估计人家作者都已经更新了无数个版本我还不知道。在我陈旧的印象中,要用LaTeX生成可复制粘贴的中文只有一种办法,就是用dvipdfmx把dvi转为pdf,而我陈旧的印象又记得dvi文件只能由latex命令生成,并且用latex编译的文档必须用EPS图形,这一直让我觉得很不爽,因为我实在不爱用EPS,比如R的postscript()设备(可生成EPS图形)不支持半透明色,而且图形中要用中文字符的话配置非常麻烦(N年前我请教了Paul Murrell,虽然搞明白了,但心里仍有疙瘩)。我的偏好是用pdflatex命令编译文档,图形也用PDF格式(pdflatex默认支持PDF和PNG图形),用R生成PDF图形也方便、漂亮,所以配合Sweave很容易生成一篇干净利索的PDF文档;但pdflatex命令直接编译生成的中文文档中,中文字符是不能复制粘贴的,因为复制出来就是乱码。所以呢,我陈旧的知识让我的这个“麻烦问题”一直没有得到解决。
近来有些奇怪,有几位R core们居然给本小子写邮件,让本小子着实感到吃惊。比如,首先是Brian Ripley,这是R core中的core,前面提到过他在R源代码中的突出贡献,这位真人不露面、网上找不着照片的大佬,前段时间给我发封邮件说,你小子的animation包的启动消息不正规啊,因为我用suppressPackageStartupMessages()无法屏蔽启动消息;我一看,R里面居然还存在这么长名字的函数,顺便学习了message()函数,从此不再用老土的cat()函数了,后来考虑了一下,干脆把启动消息去掉了,library(animation)不会再有任何提示消息。
然后是我发现Duncan Temple Lang这位不靠谱的大叔做着一些我很喜欢的不靠谱的事情,于是乎对Omegahat心向往之,一来二去聊了聊,将来有机会一定要会一会他。
Sweave对注释的处理是要么完全去除,然后R代码会被整理整齐,要么完全保留,但R代码也保留原样,而我一直希望既能保留注释又能整理代码,这才诞生了animation包中tidy.source()函数(在小邱聪明的技巧下),前段时间想想给Friedrich Leisch,也就是Sweave的作者,发封邮件说了这个事情,打探一下是否能多设置一些Sweave选项,比如把parse()和deparse()函数以选项的形式抽象出来,这样就可以实现既整理代码又保留注释的功能了,不过大叔貌似很忙,回了一封邮件就再也没有音信了,后来由于Michael Friendly对Sweave的一些功能请求在R-help上发了邮件,我们一干人等通过Duncan Murdoch间接了解到Friedrich的确很忙,不过好消息是圣诞节过后Sweave可能会有更新,届时用户可以自行设置图形设备,不必局限在PDF和EPS。但整理代码的事情仍然遥遥无期……唉,还得用硬性Hack的方法。
Martin Maechler前面提过,看到我们开R会,说要向The R Journal交报告啊,回头再跟他谈谈明年R会议的事情。
最意想不到的是,Duncan Murdoch刚才居然给我发个邮件问问题,额滴神啊,这位大叔可是Rtools的管理者、若干个包的作者(rgl等)啊。不过大叔问的是Flash的问题,还好我知道那么一点点,算是能解决。趁此机会,干脆回问两个C语言问题,子曾经曰过:问一个够本,问两个赚一个。
近期评论