Stata + Boss Ox's Framework = Easy Life

本文介绍一个由我操刀设计的 Stata 框架,简单安装一下即可大幅提高工作效率,解决 Stata 移动版经常遇到的麻烦。文末附下载链接。


Profile.do

Stata 在启动的时候会自动以 run 的模式运行与程序放在同一文件夹下的 profile.do 文件(如果有),用户可以将很多个性化的设置写在里面,使 Stata 符合自己的使用习惯,工作起来得心应手。以个人观察和周围同行的情况来看,大多数人不知道这样一个功能,即便知道也很少有人将其充分利用起来。

如果充分利用 profile.do 能给我们带来什么便利呢?那要看在没有这个文件的情况下,使用 Stata 都存在哪些痛点。例如:

  1. Stata 的命令包都在 Ado 文件夹下,但绿色版的程序却视 PLUS 和 PERSONAL 文件夹而不见,将这两个系统文件夹定位到 C 盘去(Windows 下),导致程序在分享的过程中经常找不到已经安装的扩展命令。

  2. Stata 启动后不会自动记录日志,每次都需要手动打开。偶尔出现什么问题要频繁关闭 Stata 时,会忘记继续记录日志,导致事后查询日志时两手空空。

  3. 同时进行几个项目时,每次启动 Stata 之后,都需要将当前工作目录导航至电脑上其他某个地方,这个过程往往十分繁琐(例如将不同项目放在不同文件夹,数据文件又放在其他什么地方),让人头疼。

  4. 工作告一段落,第二天继续进行的时候忘记自己做到哪里了。找个记事本记录一下还要单独打开很麻烦。

  5. 想编辑一下 profile.do 但是要找到这个文件很麻烦(在已经使用 profile.do 的情况下)。

这些问题的解决都可以通过合理编写 profile.do 来实现。

框架设计之源

我最早了解到 profile.do 是在中山大学副教授连玉君老师的 Stata 视频课程里,连老师有一套自己的 profile.do 编辑习惯,包括修改 Stata 偏好、记录日志、设定工作文件夹等。我将它运用到自己的使用中,受益匪浅,但同时也发现这套配置包含了许多个人特色,并非对所有人都适用。

结合自己的工作经验,以及在编程方面的一些思路,我有了设计一套自己的工作环境的设想,如今付诸实践。暂时没有想到好名字,将这个工作环境命名为“Boss Ox's Framework”,意为我的一套框架。这个框架将高度个性化的内容剔除,保留必要的偏好设置,自动建立日志,并提供了多项目管理的一个很好的思路。

目前这个框架已经在我周围的很多同学中进行推广,并且在不断的试用过程中,得到了修正、完善和增强。2018 年 3 月 9 日发布的这一版是可用性大幅度增强后公开发布的一版,应该可以稳定高效地提供工作环境支撑。一些新的设想将会在后期逐步实现。

不过话说回来,Stata 毕竟不是一个编程语言,只是脚本,没法搞定所有天马行空的构想,现在实现某些功能就已经挺费劲的了(参见 do 文件内容),后续升级也是要探索可行性的。

关于框架

所谓的这个框架,起始也只是一个 do 文件,用来实现自动化、简易化、快捷化的辅助性功能。由于 macOS 和 Windows 系统的差异,这个 do 文件不能通用,故编写了两个版本,分别针对各自系统进行了优化,命名为 “BOSSOX_Framework_macOS.do” 和 “BOSSOX_Framework_Windows.do”。

这套框架自动实现了以下功能:

  1. 将 PLUS 和 PERSONAL 文件夹,设定在 Stata 相对目录 Ado 文件夹下。
    这样,在移动 Stata 或者将 Stata 拷贝至其他地方时,已经安装的扩展命令会跟随移动,并自动被 Stata 识别,解决了更换 Stata 位置后,无法找到扩展命令的问题,使 Stata 可以装进 U 盘里移动使用。

  2. 自动记录日志(Log)和命令日志(CmdLog)。
    每次启动 Stata 时以时间为名称保存这两个记录,并且从不自动删除,所以可以彻底忘记要时刻保存日志的事情了,想要查询的时候直接回去翻看文件夹就好。
    有一个 BUG:macOS 下启动时设定日志的话,日志记录状态会在程序中显示出来,但是 Windows 下是无法显示的。这会给人一种错觉,认为 Stata 并没有在记录日志。但其实用 log 命令去检验的话,会发现日志记录千真万确是打开着的。习惯就好。

  3. 建立了 QuickStart 文件夹体系。
    这是干什么的?用于多项目管理。举例来说,一个用户近三个月来同时作者三个项目,项目的主要文件分别存放在了 D:\StataProjects1E:\temp\pro2F:\SCI\final3 中。传统情况下,这个用户打开 Stata 的第一件事就是:想一下今天要做的项目放在了哪里,然后用一串 cd 命令将当前工作目录(PWD)切过去。
    有了 QuickStart 事情变得不一样。这个用户对于每一个进行中的项目,都写一个 do 文件放在这里,充当访问这个项目的快捷方式。这个 do 文件中可以最少只写一句话,即将目录切换至这个项目所在的目录,例如在 1.do 中写 cd D:\StataProjects1,在 2.do 中写 cd E:\temp\pro2,3.do 同理。
    这个框架在初始化之后,会自动将当前工作目录切换至 QuickStart 文件夹,并在输出中列出该文件夹下的所有 do 文件,从而可以直接以 do 或者 run 的方式运行 1.do 将目录切换至第一个项目的主文件夹,2、3 同理。
    如果某些大型的项目,在每次工作开始前都要进行一定的初始化设定的话(例如声明几个全局的 macro 来存储一些经常访问的内容),也可以将这些代码写在这个快捷方式 do 文件中,从而在切换至项目主文件夹的过程中,完成这些操作。
    可以用 doedit 和 rm 命令来方便地管理 QuickStart 文件夹里的内容。

  4. 提供一个全局记事本(Notes.txt)。
    可以直接在 Stata 中查看记事本的内容,然后通过 Stata 命令来打开这个文本文件进行编辑。可以当做 Todo 或者 Memo。
    这个东西是当年我要做的事情太多太琐碎了,常常记不清上次做了什么该做什么,而设计的。当时是针对于一个项目而言的,在加载完 QuickStart 里的快捷方式之后显示这个记事本,现在拿来当做一个全局性的功能来用。

  5. 快速编辑 profile.do 文件。
    相对前文,这只是一个细枝末节了。框架提供了一个命令来快速地打开 profile.do 文件,无论当前工作目录是什么鬼地方。

灵活使用这些工具可以使科研工作变得方便许多,省去很多烦恼。不过也有坏处——女朋友去找导师谈论文方向的时候,在导师电脑上操作 Stata 就忘记了开启日志记录功能,因为平常都是全自动的,没这个习惯了哈哈。

这个框架除了要求被放置于 Stata 文件夹,并且在最后会将当前工作目录切换至 QuickStart 外,与程序其他内容没有关联,是高内聚、低耦合的。用户只需要在 profile.do 中增加或删除一条命令,即可实现插件的安装和卸载,这样用户无需对 profile.do 进行大的改动,不会影响已经自定义的其他功能。

使用说明

插件化的设计思路,使得这个插件的安装和卸载变得十分简单。

A 安装

  • 复制框架 do 文件到 Stata 程序所在文件夹。
  • 在这个文件夹里如果没有 profile.do 的话,建立 profile.do,有的话对其进行编辑,根据所使用的操作系统,在 profile.do 中任意位置加入下方对应的命令:
    // Load Boss Ox's framework for macOS
    noisily run BOSSOX_Framework_macOS.do
    
    // Load Boss Ox's framework for Windows
    noisily run BOSSOX_Framework_Windows.do
    

如此简单即完成了框架的安装,下次启动 Stata 时,若除了在 Available QuickStarts 部分下有找不到文件的提示,没有其他错误提示,即为安装成功。

注意:上文说在 profile.do 的任意位置添加命令,是原则性的。实际上,因为框架初始化会依赖于 do 文件被调用时 Stata 的当前工作路径,要求必须是 Stata 程序所在的位置,所以不能在 profile.do 中更改当前工作路径的命令后面放置加载框架的命令,除非在实际加载框架前,当前工作路径又被调整回初始值。

B 加载

框架安装后,每次启动 Stata 会看到如下图所示的初始化界面。在 Windows 系统中,当 QuickStart 中没有 do 文件时,Available QuickStarts 部分可能会提示无法找到文件的错误,这是正常现象。

Boss Ox's Framework Windows 版加载效果图

图中所示信息的一些解释:

  • BOSS OX 为作者信息,下方日期为版本号,Beijing 表示制作地点。
  • Global Framework Commands 部分为框架命令,在命令窗口直接输入如下所列的可用命令,回车即可执行操作。
  • Available QuickStarts 部分列出了 QuickStart 文件夹下的所有 do 文件。由于框架会将当前工作目录最终切换至 QuickStart 文件夹,所以可以直接 run 或者 do 这些 do 文件,来实现快捷方式似的跳转。
  • Notes 部分显示 Notes.txt 的文本内容。

C 命令

  • $fw_profile:编辑 profile.do 文件。
  • $fw_config:编辑 BOSSOX_Framework_macOS.do 文件(以 macOS 为例)。
  • $fw_home:将当前工作目录切回到 QuickStart 文件夹。
  • $fw_autolog:显示已有的自动日志(Log)。
  • $fw_autocmdlog:显示已有的自动命令日志(CmdLog)。
  • $fw_clearlog:删除全部自动日志(Windows:当前日志除外)。
  • $fw_clearcmdlog:删除全部自动命令日志(Windows:当前日志除外)。
  • $fw_note:显示 Notes.txt 的文本内容。
  • $fw_editnote:用记事本编辑 Notes.txt 的内容。
  • $fw_help:显示框架可用的命令和说明。
  • $fw_about:显示框架的关于信息。

D 文件

加载框架之后,会生成下图中 Framework 文件夹结构,这里存放着框架所处理的全部文件。

框架所生成的文件结构

其中 AutoLog_CmdLog 存放命令日志,AutoLog_Log 存放日志,QuickStart 存放用户编辑的充当快捷方式的 do 文件,Notes.txt 是记事本文件。

E 拆卸

  • 删除 BOSSOX_Framework_macOS.do 文件(以 macOS 为例)。
  • 从 profile.do 中将先前安装框架时添加的命令删除。
  • 删除 Stata 文件夹下的 Framework 文件夹,这是框架运行时生成的文件;如果不希望删除日志和命令日志的话,请提前将这些东西备份出来。

技术细节

A 如何生成记事本?

我没找到 Stata 里直接生成文本文件的命令,所以使用了一个曲线救国的办法。CmdLog 命令会生成一个文本文件,并且不强制指定扩展名。与 Log 命令相比,在不输入任何命令的情况下,前者不会向文件中写入任何内容,所以文件为空;而后者会把程序启动时显示的信息都囊括进去。所以实际上是用 CmdLog 命令来实现的。

B 如何在暂元中保存引号?

help quote 命令可以查询到 Stata 关于引用的说明,但官方的例证过于繁琐了,不如 SSCC(Social Science Computing Cooperative)写的这篇文章《Stata Programming Tools》更简明扼要。

简单说,Stata 没有转义字符的概念,当传统的双引号不能表达一个内容为双引号的字符串时,可以使用复合双引号来引用字符串,即 `""'(反引号+双引号,双引号+单引号)。例如:

global test =  `"""'
macro list test

输出结果为一个双引号 "

在复合双引号中使用单引号会存在问题,所以需要灵活地和普通双引号进行拆分和加和的配合,从而达到向暂元中存放复杂命令的问题,尤其是存放 display 命令的时候。

插播:怎样用 Markdown 打出有反引号(`)的行内代码块?
波浪线(~,Tilde)按键上的另一个符号,叫做 “反引号”。在 Markdown 语法中,用两个反引号括起来的内容被标记为行内代码块。如果想在代码块中放置反引号,则需要增加用于标记开头和结尾的反引号的对儿的数量,例如两个:

``there is a ` in the code block``

这段代码的效果是:there is a ` in the code block
但如果代码中的反引号出现在开头或结尾,会影响转码的识别,所以需要在代码首尾再额外添加一个空格:

`` ` is at the beginning of the code block ``

这代代码的效果是:` is at the beginning of the code block
我是因为要用代码块打出复合双引号才碰到的这个问题,现查了一下 Markdown 语法说明 中关于反引号(`)的使用规则。我原以为转义字符反斜杠(\)是可以完成这个任务的,但遗憾的是在两个反引号括起来的代码块中使用反斜杠来转义中间的一个反引号行不通。反斜杠也只能转义有数的几个特殊字符,这一点在语法说明的文末有介绍。

C 其他小点

  • 使用 global macro 保存 Stata 命令和参数,形式上作为用户输入的当做框架的命令。
  • 使用了 C 级系统返回值。

下一步展望

如果研究生毕业之后还有机会经常用到 Stata,或许我还会有动力继续完善这个作品。其实现在就有进一步扩展这个框架的想法,只因为预计马上毕业之后就再也不用,所以就犯懒了。后续有可能根据用户反馈进行微调和 BUG 修复,大版本的更新就看心情了,红红火火恍恍惚惚呵呵哈哈嘿嘿!毕竟当前的设计还是存在一些弊端的,比如对文件名的高度依赖,以及会占用全局暂元等等。

简单记一下未来的发展方向吧:

  • 用 Program 充实当前功能。
  • 区分针对框架的命令和框架下内容的命令,例如自动拆卸框架。
  • 检测框架所需的 macro 是否已经被定义,若是,申请新名称,避免冲突。
  • 提供直接打开日志的命令和打开日志文件夹的命令。
  • 提供管理 QuickStart 文件夹内容的命令。
  • 没有 Notes.txt 的情况下,新建内容为 “Hello World!” 的文件,打招呼。

……


欢迎广大亲朋好友来尝试一下,并反馈给我。
下载地址(2018.03.09):百度云盘

推荐阅读更多精彩内容