注:本文是作者寒假在家闲着没事写的,纯属娱乐,熟悉R的朋友自己查帮助就可以了。?select.list ?choose.files等等。
R语言中的简单人机交互与文件操作
中国人民大学统计学院 谢益辉 众所周知,R语言在编写统计类程序上有着其它统计软件无法比拟的优势,而用R自行编写程序时,若加入一些人机交互的操作界面,对于“枯燥乏味”的编程工作无疑会带来几分生动,同时也增加了用户使用程序的灵活性。在此,本文简单介绍一下关于人机交互操作和文件操作的几个函数。
一、简单的人机交互对话框
R的utils包2中提供了一些我们常用的人机交互操作函数,例如信息框(Message Box)、选择列表、文本框、打开文件/文件夹的对话框等等;下面依次给予说明: 1、信息框与文本框
winDialog(type = c("ok", "okcancel", "yesno", "yesnocancel"), message) winDialogString(message, default) |
|
前者是信息框,后者是文本框,这二者的作用分别是给用户相应的提示信息和让用户输入需要的信息;信息框的type参数有四种选择,分别表示“确定”“确定、取消”“是、否”“是、否、取消”,message参数是给用户的提示信息;文本框的message参数意思同前,default参数是默认的输入文本。
信息框的返回值为相应的字符如"YES"、"NO"等,文本框的返回值为输入的字符;编程人员可以根据用户的不同输入来执行相应的程序。
例:
x = as.numeric(winDialogString(message = "911 - 711 = ?", default = "")) # 输入的为字符,需要转化为数值 if (is.na(x) | x!= 200) { winDialog(type = "ok", message = "I'm a little fool! -_-//")} |
|
2、列表框
| select.list(list, preselect = NULL, multiple = FALSE, title = NULL) |
|
list参数为字符型向量,preselect为预先选中的项目,multiple用来设置是否可多选,title为对话框的标题;函数返回值为选中的项目(构成的字符型向量)。
例:
> select.list(list = letters[1:5], preselect = "c", multiple = FALSE, title = "Select a letter")# 设置c为预选项;单选 [1] "c" > select.list(list = LETTERS[1:5], preselect = NULL, multiple = TRUE, title = "Select a letter")# 可多选 [1] "B" "D" "E" |
|
图1:略(参见附件)
3、获得文件/文件夹的路径
choose.files(default = "", caption = "Select files", multi = TRUE, filters = Filters, index = nrow(Filters)) choose.dir(default = "", caption = "Select folder") |
|
二者分别为选择文件和文件夹的对话框;default参数设置默认的路径,caption设置对话框标题,multi设置是否可多选,filters设置选择的文件类型(扩展名)3,index为将filters参数中第几种文件类型设置为默认类型;
例:
> choose.files(caption = "Choose some files", multi = TRUE, filters = Filters, index = nrow(Filters)) [1] "E:\\R\\dialog.r" "E:\\R\\for.r" "E:\\R\\layout.r" > fltr = matrix(c("Microsoft Office Document", "*.doc; *.xls; *.ppt"), nrow = 1) > choose.files(caption = "Select files", multi = FALSE, filters = fltr) [1] "E:\\Book1.xls" > choose.dir(default = "", caption = "Select folder") [1] "D:\\YEARBOOK\\2006" |
|
显然这两个函数省去了我们手工敲入文件/文件夹路径(往往是比较长)的麻烦,而可以改用鼠标方便点选。
上面介绍的一些对话框可以结合起来使用,它们也涵盖了两种基本的交互功能:提示用户和让用户输入。此外,对于统计软件来说,我们很希望能看见类似电子表格之类的界面以便录入和修改数据,这时R中的三个函数data.entry()(或者dataentry()、de())、edit()和fix()就比较有用了。
当然,要想设计出比较好的图形用户界面(GUI),仅靠这几招三脚猫功夫肯定不够,若对界面设计感兴趣,可以研究tcltk包,这个包提供了很详细的函数用来设计构成界面的元素(包括按钮、标签、复选框、列表框等等);提起tcltk包,也不得不介绍一下Rcmdr包——这算是目前R中最完善的一个GUI了,它的界面就是基于tcltk包设计的。
二、R中的文件操作
R可以对存储介质中的文件进行读写、复制、删除等操作,这对于程序的输入输出也提供了方便。下表中给出了关于文件操作的一个简要总结说明:
表格:略(参见附件)
三、杂项
另外一些三脚猫的伎俩:
·习惯使用Windows的用户都很熟悉传说中的“CV大法”——Ctrl + C和Ctrl + V,说的也就是剪贴板(clipboard),在R中利用剪贴板也能给我们省去不少麻烦,尤其是读入和输出数据时,我们可以利用剪贴板为媒介,例如read.table()和write.table()这两个函数的file参数都可以用"clipboard":比如先从Excel或者别的什么地方Copy一块(比较“规则”的)数据,然后在R中用read.table("clipboard")把数据读进来;当然也可以用write.table(x, "clipboard")把数据读入剪贴板然后粘贴到别的程序中;对于小批量的数据转移,这是特别方便的。
·browseURL()函数可以调用默认的Internet浏览器来打开一个网页,例如: browseURL("www.cos.name")
·R作图时有一样东西让人比较恼火,那就是一些元素的位置不太好获得,比如图例(legend),或是想自行添加的文本,因为没办法用鼠标把这些东西拖拽到合适的地方——在R的世界,鼠标往往是个废物……其实,可以利用一下locator()函数,它能获得鼠标在图上点击位置的坐标,比如我们用它来添加图例: plot.new(); legend(locator(1), legend = 1:3, lty = 1:3, col = 1:3) 其中locator()函数的参数1表示点击1次之后就停止,详情请自行查阅帮助。
附:文件操作的程序(参见zip文件中的dialog.r和file.r文件)
f.access = function() { x = choose.files() if (length(x) > 0) { xx = NULL for (i in c(0, 1, 2, 4)) { xx = cbind(xx, file.access(x, mode = i)) } colnames(xx) = c("是否存在?", "可执行?", "可写?", "可读?") print(noquote(apply(xx, 2, function(x) factor(x, levels = c(0, -1), labels = c("是", "否"))))) } } |
|
f.info = function() { ch = nchar(select.list(c("单个/多个文件属性", "单个文件夹属性", "单个文件夹下所有文件/文件夹属性"), title = "欲查看:文件/文件夹属性?")) if (ch == 17) x = choose.files() if (ch == 14) x = choose.dir() if (ch == 31) x = list.files(choose.dir(), full = T) if (length(x) > 0) { xx = file.info(x) colnames(xx) = c("大小/字节", "是否为目录", "模式", "修改时间", "创建时间", "最后访问时间") xx[, 2] = factor(xx[, 2], levels = c(T, F), labels = c("是", "否")) print(xx) } } |
|
f.create = function() { if (file.create(winDialogString(message = "请输入文件名(包含路径)", default = file.path(R.home(), "newfile")))) { winDialog(message = "文件创建成功!") } else { winDialog(message = "文件创建失败,请检查路径是否正确!") } } |
|
f.exists = function() { x = winDialogString(message = "请输入文件名(包含路径)", default = "") if (file.exists(x)) { winDialog(message = paste("文件", x, "存在!")) } else { winDialog(message = paste("文件", x, "不存在!")) } } |
|
f.remove = function() { x = choose.files() if (length(x) > 0) { if (winDialog("yesno", "永久删除选中的文件?(不可恢复!)") == "YES") { file.remove(x) } } } |
|
f.rename = function() { x = choose.files(multi = F) if (length(x) > 0) { xname = winDialogString(message = "请输入新的文件名(不含路径):", default = "") if (!file.rename(x, paste(dirname(x), xname, sep = ""))) { winDialog(message = "重命名失败!") } } } |
|
f.append = function() { x1 = choose.files(caption = "选择原始文件") x2 = choose.files(caption = "选择追加文件") if (length(x1) + length(x2) >= 2) { file.append(x1, x2) } } |
|
f.copy = function() { x = normalizePath(choose.files()) xdir = choose.dir(caption = "选择目标文件夹:") if (length(x) > 0 & xdir != "") { y = list.files(xdir) xshort = basename(x) ovwt = F if (length(intersect(xshort, y)) != 0) { ovwt = (winDialog("yesno", "目标文件夹下有同名文件,是否覆盖?") == "YES") } file.copy(x, xdir, ovwt) } } |
|
f.dir.create = function() { xdir = choose.dir(caption = "选择目标文件夹:") folder = winDialogString(message = "请输入新文件夹名:", default = "") if (!xdir == "" & !folder == "") { if (!dir.create(file.path(xdir, folder))) { winDialog(message = "创建文件夹失败,请检查文件夹名称!") } } } |
|
f.list = function() { xdir = choose.dir(caption = "选择目标文件夹:") full = (winDialog("yesno", "是否显示完整路径?") == "YES") if (xdir != "") { print(list.files(xdir, full.names = full)) } } |
|
f.unzip = function() { x = zip.unpack(choose.files(filter = matrix(c("Zip files (*.zip)", "*.zip"), 1)), choose.dir(caption = "选择目标文件夹:")) if (x != 0) { winDialog(message = "文件解压失败,请检查原压缩文件或者目标文件夹!") } } |
|
f.download = function() { xurl = winDialogString(message = "请输入文件地址:", default = ifelse(is.null(readClipboard()), "http://", readClipboard())) if (xurl != "") { xdir = choose.dir(caption = "选择下载目标文件夹:") if (xdir != "") { download.file(xurl, file.path(xdir, basename(xurl)), mode = "wb") } } } |
|
f.url.show = function() { xurl = winDialogString(message = "请输入文件地址:", default = ifelse(is.null(readClipboard()), "http://", readClipboard())) if (xurl != "") { url.show(xurl) } } |
|
action = select.list(c("1. 文件属性", "2. 文件(夹)信息", "3. 创建文件", "4. 文件是否存在", "5. 删除文件", "6. 重命名文件", "7. 追加写入", "8. 复制文件", "9. 创建文件夹", "10. 文件名列表", "11. 解压zip文件", "12. 下载文件", "13. 显示网页文件"), title = "选择操作") if (action == "") { winDialog(type = "ok", message = "没有选择任何操作!") } else { action = as.character(as.numeric(substr(action, 1, 2))) switch(action, "1" = f.access(), "2" = f.info(), "3" = f.create(), "4" = f.exists(), "5" = f.remove(), "6" = f.rename(), "7" = f.append(), "8" = f.copy(), "9" = f.dir.create(), "10" = f.list(), "11" = f.unzip(), "12" = f.download(), "13" = f.url.show()) } |
|
下载全文: 谢益辉:R语言中的简单人机交互与文件操作>>>
|