作为半个码农,有两次程序侦察工作窃以为得意。一次是统计之都网站改版时的豆腐块对齐工作,这已经说过了;另一次是今天琢磨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的完美支持在近两个月内又不太可能了。
一个多月以前,我向LyX官方提交了三个基于ctex宏包的layout文件(见#7495号“传票”),分别用来写中文论文、书籍和报告,熟悉ctex的一看就明白这是什么意思。这些新的layout将在2.0.1中被收录,顺利的话,六月份(可能是下旬)会发布出来。到时候,只要你的LaTeX中安装了ctex宏包,LyX文档设置中就会出现三个类:
- article (CTeX)
- book (CTeX)
- report (CTeX)
如果你用模板新建文档(Ctrl+Shift+N),那么将会看到一个模板文件:
- ctex.lyx
用模板的好处在于可以省去一些繁琐设置,对中文文档来说,这些设置包括:
- UTF8编码(推荐),包括Class Options中的Custom一栏填入UTF8(这个选项将传送给ctex宏包),另外,还要把语言修改为简体中文,语言的编码设置为XeTeX (utf8)
- 如果用Adobe中文字体并且用pdflatex编译,那么上面的Custom一栏还需要填入
,adobefonts,此处不解释,我假设你熟悉ctex宏包;否则要用XeTeX字体并用XeTeX编译 - 语言包的设置最好清空(设置为Custom,填入%),据我所知,LyX采用的babel宏包对中文文档完全是累赘(多出来一些
\selectlanguage{}的命令,很讨厌) - 导言区可能需要加入
\DeclareRobustCommand\nobreakspace{\leavevmode\nobreak\ },我不知道这是谁的bug
最重要的是第一项设置,就是编码,如果出错,再看后面三项。
还是DJ兄给力,给的这篇关于如何使用LaTeX浮动召唤术的神帖相当的有用。书中的那些稍微高一点的图形现在都乖乖浮动到页面上方去了,下面的文字如流水般淌过。这事情,只能用《十全九美》第5分06秒的场景描述了:
对于“按下葫芦浮起瓢”(卢编语,非常贴切)的LaTeX浮动,现在我们可以引用《疯狂的石头》10分17秒的场景来描述:
尽管前面我说参考文献很可恶,但长期在此溜达的客官也许可以发现以上两部老片子是我常用的参考文献。
又及:晚上做了真正意义上的红烧肉,红烧肉呀么红烧肉,没得五花肉,果然是烧不成的。
又又及:关于LyX和pgfSweave的工作似乎惊动了LyX中央,今天“上面”来人了,也许LyX 2.0里面我能把pgfSweave给整进去。这是个好事。
再及:MSG包已经扔到CRAN上了,不过Windows版本的包目前还没编出来。这本书的最后一节也已经收到,但关于R介绍的一章要大幅度重写,然后才真正算是初稿完成,万里长征走完了一步。
周老师分享文章一篇,《谈谈时间管理–陶哲轩》。跑题党眼中的两处问题:一、新浪的PageRank不可能是6,我后来特地看了一下,是8,陶的博客PR要是能赶上新浪,那新浪就得关门了,吹捧不带这么吹的;二、陶曰:正在研究宏,以便能够快速输入\begin{theorem}…\end{theorem}之类的LaTeX代码,我心想,嗨,费那事儿干嘛,LyX不是现成的吗。时间紧,话题不展开,不过陶的确是个牛人。
又及:最近心中有些不安分。这种不安分加密之后就是:余弦!余弦!余弦!
又又及:谁来给我讲讲木遥是谁?傅立叶变换写得很好,再具体一点就更好了,得拉到统计之都来。
如题。LyX今天放出了RC(Release Candidate)版本1,忐忑安装试了一把,中文书稿仍然可以正常编译,阿弥陀佛。这书稿到下星期结束时,大约可以写完了。
外一篇:傻
在美帝呆久了人容易变傻,不知道是自我心理暗示还是真的容易变傻,总之本小子觉得自己一直有变傻的趋势。傻博士读到一定程度,也许真的会走路撞着电线杆子说对不起。变傻的特征之一就是不会说话,开口容易说错话,说话不过脑子。统计男就统计男嘛,说人家市侩也太过分了,阿弥陀佛,罪过罪过。以后各位客官看见这种不过脑子的话可以直接上脚踹。
话说回来,上一篇日志标题为啥叫“慢”呢,这一点我在给COS管理人员的邮件中解释过:现在的娃儿有返古风,据本小子揣测,原因是古文读起来慢,而因为读不快,所以才能集中精力想,因为脑子跟上了,东西才能读得进去。你说这一天到晚看那么多东西,有几样看得进心里去啊。
说到COS,这一帮人,主站一个月憋一篇文章,有人说这更新忒慢了吧。我说,慌啥,写好老文章就够了,有一篇让人读十遍的文章,比十篇让人读一遍的文章强多了。铺天盖地发表更新,有嘛用。
转眼间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一下就解决了)。
我回忆了好半天,还是想不起当初我为什么对LyX留下了一个错误的印象:它生成的LaTeX文档的前四行是无效的。即这样的代码:
\batchmode
\makeatletter
\def\input@path{{\string"path/to/some where/\string"/}}
\makeatother
当年我并没有仔细研究第三行,但凭感觉,它是用来定义文档中的外部文件的输入路径的,比如\includegraphics{}的根路径。这个感觉并没有错,但当年阴差阳错失败了。我发现LyX的文件名弄乱机制(filename mangling)是因为当时想在Sweave中输出动画,因而需要使用animate包和\animategraphics{}命令,但是死活由于找不到输入文件而报错,我花了好几天时间,终于发现原来有这么个机制,以及LyX的编译过程(先复制到临时文件夹再编译)。于是我只好想办法把动画文件先复制到临时文件夹再编译,这当然不是个好办法。还有Sweave,我都是用R脚本把需要的文件复制到LyX的临时文件夹下再让LyX编译,比如需要读入的数据和需要引用的图片文件等。这都是为了让LyX不要抱怨找不到文件。
今天在考虑animation包中的saveLatex()如何在Sweave中使用,于是再度看了一下LaTeX的animate宏包的文档,看着看着,突然见到其中有个单词“Important”可以闪动,于是好奇它是怎么做到的,自然也就把源文档找出来看;打开源文档,无意看到这么一句:
\graphicspath{{files/}}
凭直觉,我觉得这是指定图片文件的根路径,即:文档中的图片引用都以files/为基准,在这个文件夹下去寻找。抬手Google了一下,没错,是这样。我想,这不就是我很久以来想要的东西么,只要定义了图片的输入路径,就不必发愁在LyX文档目录和临时文件目录下拷来拷去了。试了一下,对图片\includegraphics{}的确管用,但由于我用pgfSweave,图片都是用\input{}的方式,这招不管用。
恍惚间,想起了本文开头的那几行命令,琢磨着为什么它们不管用呢,难道有bug?再在LyX中输入了几行LaTeX代码试了试,\includegraphics{}和\input{}都不写绝对路径,只写相对于LyX文档的相对路径,编译,居然成功了!这简直是个灵异事件。
这下R代码中可以setwd()到文档目录了,解决了许久以来的一大麻烦——这是跟人说不清道不明的麻烦。缓存也有了(包括R对象的缓存和图片的缓存),代码高亮也有了,这下可以理直气壮说pgfSweave好用了。
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。本来我就对急帖心存反感,一问还不是真的急(就像听了个狼来了的故事),这以后旁观者到底还该不该急呢?
我不确定这是不是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命令直接编译生成的中文文档中,中文字符是不能复制粘贴的,因为复制出来就是乱码。所以呢,我陈旧的知识让我的这个“麻烦问题”一直没有得到解决。
有些LaTeX用户可能觉得敲代码太费事了,那么这里推荐一下LyX。LyX是一个所见即所得的编辑器,因为它基于LaTeX,所以排版质量没啥好说的。关键是它可以和Sweave结合起来用,只要到CRAN下载LyX相关配置文件就可以了。
详细使用方法参见R News 2008年第1卷的第一篇文章”Using Sweave with LyX”。


近期评论