R使用经验
本文将以逐渐增加的方式总结一些R的小问题的处理方法。 这里的一部分小窍门来自Grant V. Farnsworth: Econometrics in R。
重要链接
R-Forge: http://r-forge.r-project.org/ 各种R附加软件包的存放地点。
Access表读写
假设有Access数据库在文件c:/Friends/birthdays.mdb中,内有两个表
Men
和Women,每个表包含域
Year
, Month
, Day
, First Name
, Last Name
, Death
。域名应尽量避免用空格。
例1:读入女性所有信息:
> require(RODBC)
> con <- odbcConnectAccess("c:/Temp/birthdays.mdb")
> women <- sqlQuery(con, 'select * from Women')
> print(women)
> close(con)
例2:显示数据库目录
> require(RODBC)
> con <- odbcConnectAccess("c:/Temp/birthdays.mdb")
> # Table names. Ignore those starting with 'MSys'
> sqlTables(con)$"TABLE_NAME"
> # Column names in a table
> sqlColumns(con, "Women")$"COLUMN_NAME"
> close(con)
例3:较复杂的查询
> require(RODBC)
> con <- odbcConnectAccess("c:/Temp/birthdays.mdb")
> # Read Year, Last Name and First Name.
> # Rename Last Name to LastName, First Name to FirstName
> # Read first 5 rows where First Name is not 'Carl'
> men <- sqlQuery(con, "select top 5 Year, [First Name] as FirstName, [Last Name] as LastName from Men where [First Name]<>'Carl'")
> close(con)
Excel表格读写
基本办法是转换为其他格式如CSV格式再读。在Windows下有xlsReadWrite包,可以读写.XLS文件。RODBC包也可以支持Excel文件的读写。
小量数据可以选中一个矩形区域复制,然后在R中用
> myDF <- read.delim("clipboard")
也可以从R中复制数据集:
> ## export 'iris' data to clipboard
> write.table(iris, "clipboard", sep = "\t", col.names = NA)
> ## then open up MS Excel and paste (ctrl-v) in iris data
用ODBC读取Excel文件:
> library(RODBC)
> MyExcelData <- sqlFetch(odbcConnectExcel("Test.xls"), sqtable = "Sheet1", na.strings = "NA", as.is = T)
> odbcCloseAll()
用xlsReadWrite的例子:
> library( xlsReadWrite )
> ### create some test bike data
> tdat <- data.frame( Price = c( 6399, 3699, 2499 ), Amount = c( 2, 3, 1 ),
Date = c( 39202, 39198, 39199 ), row.names = c( "Pro machine", "Road racer", "Streetfire" ) )
> ### write
> write.xls( tdat, "bikes.xls" )
> ### read and check: read as data.frame
> bikes1 <- read.xls( file = "bikes.xls" )
> if (!identical( tdat, bikes1 )) stop( "oops, not good..." )
> # read as data.frame (custom colnames, date as iso-string)
> bikes2 <- read.xls( file = "bikes.xls", colNames = c( "", "CHF", "Number", "Date" ),
from = 2, colClasses = c( "numeric", "numeric", "isodate" ) )
> if (!all( tdat$Date == isoStrToDateTime( bikes2$Date ) )) stop( "oops, not good..." )
> # read as matrix
> bikes3 <- read.xls( file = "bikes.xls", type = "double" )
> if (!identical( as.matrix( tdat ), bikes3 )) stop( "oops, not good..." )
简单交互式图形界面
R 通过对Tcl/Tk的支持(tcltk包)实现了图形界面(GUI)功能,但是需要的编程略微复杂。rpanel是建立在tcltk包基础上的一个包,它 用很简单的几个语句就可以建立一个调控运行参数的界面,主要用来实时更新图形,修改界面上的控制参数则图形立刻刷新。真的很容易。
表格数据
table()计算频数。
tapply(x, fac, func)按fac对x分组在每组内计算函数func。fac还可以是由若干因子向量组成的列表,这时将交叉分类后计算func函数。
几个因子完全组合的结构数据集可以用expand.grid(li)实现,li是一个列表,每个列表变量包含一个因子的水平。如果ll是某个包含若干因子变量的列表,则expand.grid(lapply(ll, levels))可以构造所有可能水平组合的数据框。
要把矩阵按其显示格式写入一个文本文件,办法如
write(t(A), file="filename", ncolumns=ncol(A)).
在C++/C中使用NA值
有时需要把NA传到C++/C中。为此,C中要包含R.h头文件,并用ISNA(x[0])这样的方法判断x[0]是否为NA,编译时最好用标准的
R CMD SHLIB yourcprog.cpp
方法编译。在R中调用时.C中要加上NAOK=TRUE选项。
Linux中非超级用户安装包
假设你在自己的主目录下建立了.R/library子目录,并建立了一个~/.Renviron文件,其中包含如下行:
R_LIBS=”~/.R/library”
则可以把R的附加包安装在自己的目录中:
R CMD INSTALL -l ~/.R/library mypackage.tar.gz
进入R后可以直接访问在~/.Renviron中定义在R_LIBS目录中安装的包。
运行记录
数据分析运行中间可能输出大量的信息,在调试程序时可能需要查看这些信息。在Emacs中用ESS支持直接在Emacs窗口中运行R当然可以保存这些输出,但是在Emacs中运行如果出错(尤其是调用自己编写的C程序的错误)不容易恢复。用sink()函数可以保存输出到文件,但这时在屏幕上就看不到输出。其实,sink()函数加一个split=TRUE选项就可以实现既输出到文件同时又显示在屏幕的效果。如果图形也能作到这点就好了。
在R命令行中设置当前工作目录
用getwd()查询当前工作目录,用setwd('subdir')设置当前工作目录。 调用list.files()可以查看当前目录中内容, 用list.files(pattern='.*[.]r$')可以列出所有以“.r”结尾的文件。
集合函数
union(x, y)
intersect(x, y)
setdiff(x, y)
setequal(x, y)
is.element(el, set)
fft的数学公式
R中fft函数可以进行离散傅立叶变换。 设x为长度n的向量,y=fft(x),则
y[k] = sum(x * complex(argument = -2*pi * (0:(n-1)) * (k-1)/n))
即
w_k = \frac{k-1}{n}, k=1,2,...,n
y_k = \sum_{j=1}^n x_j \exp(-i 2\pi w_k (j-1)).
注意没有除以n。另外,若y=fft(x), z=fft(y, inverse=T), 则x == z/length(x)。
R的日期类
Date是R的日期类,实际保存为实数值。转换如d=as.Date("1996-03-17", format="%Y-%m-%d"), 而显示可用如format(d, format="%Y-%m-%d")。格式中%Y是四位的年份,%m是数字的月份,%d是日期,%y是两位的年份,%b是英文所写的月份,%B是英文全称的月份。参见strptime的帮助。
顺便提一句,在SAS中如果要把如s=”1997-03-15”这样的字符串值转换成SAS日期,方法是date=input(s, yymmdd10.)。
数据框横向合并
merge 函数。
巨大文件的读取
先用file打开,然后用readLines分批读入, 或用scan加what参数和nlines参数分批读入。
读入复制到系统剪贴板中的数据
read.table("clipboard")
回归系数估计的方差阵
rs <- summary(lm.res)
CovMat <- rs$sigma^2 * rs$cov
加权回归
只要在lm调用时加weight选项。
Logit和probit回归
用glm。
多项logit回归
用nnet包中的multinom函数。
有序Logit/Probit
用MASS包中的polr函数。
带删失变量的回归
用survreg并指定dist="gaussian"即可。
分位数回归
用quantreg包中的rq函数。
稳健回归
用MASS包中的rlm函数。
非线性最小二乘
用nls函数。
时间序列函数
lag可以计算滞后序列,但只能作用于时间序列对象,对一般向量会得出错误结果。 diff计算差分。ts.union可以形成多元时间序列。 filter函数可以计算递推的或卷积的滤波。 arima可以拟合ARIMA模型。 fracdiff库的fracdiff可以拟合分数ARIMA模型。 tseries包中的garch可以拟合GARCH和ARCH模型。 fSeries包中的garchFit可以拟合较复杂的包含GARCH的模型。 acf和pacf函数可以作自相关和偏自相关图。
时间序列检验
car包中的durbin.watson函数可以对lm对象进行Durbin-Watson自相关检验。 ts包中的Box.test可以进行Box-Pierce或Ljung-Box白噪声检验。 tseries包中的adf.test可以进行Dickey-Fuller单位根检验。
curve函数
用于函数或表达式作图,与add=T选项配合可以在已有的图上添加曲线。
等值线图
contour函数。可以用contourLines添加。 lattice包中有类似的levelplot和contourplot函数。
添加标注
用text, lines, points, arrows,legend等。用locator定位。
输出到图形文件
直接用图形设备postscript, pdf, png, jpg, xfig等。
图中用数学符号
用如main=substitute(y==Psi*z-sum(beta[0]^gamma)),会变成数学符号。 下标用方括号表示。等号用两个等号表示。 还可以给substitute一个额外的list参数表示要代入实际值的变量。 混合文本如
main=substitute(paste("t-stat of ", beta[0]))。
Kronecker积
用A %x% B表示。
优化
optim, nlm, optimize。 类似作用的有uniroot(一元方程求根), diriv(数值微分),constrOptim(约束优化)。
数值积分
一元用integrate,多元用adapt包中的adapt函数。
代替循环的函数
对矩阵用apply,对列表用lapply,对向量用sapply。
计时
用system.time(表达式)计算一个表达式的运行时间; 用proc.time得到当前时间,两次调用的差表示时间间隔。
在为R准备的C程序中使用R的随机数发生器
要调入
R CMD SHLIB mycode.c
错误处理
在options函数调用中设error=recover可以使得出错时进入调试状态。 设warn=1可以使警告信息输入不滞后。 设warn=0取消警告信息,而warn=2使警告信息变成错误。
输出为LaTeX表
用Hmisc包中的latex函数,如latex(summary(lm(y~x)))。 或用xtable包中的xtable函数。用Hmisc的latex函数时,加NA=””可以把缺失值显示成空白,输出数据集时,行名将作为第一栏。
用RPanel建立图形界面
用rp.control()函数建立一个窗口,用title指定标题。返回值保存一个代表此窗口的列表变量,列表中为图形数据。rp.control多余的参数被保存在列表中。如:
density.panel <- rp.control(title="Density estimation",
y=A1203, sp=r/8)
其中y,sp,model是额外的变量,被存放在结果列表density.panel中。
在窗口中添加控件时以窗口变量为第一自变量,如:
rp.slider(panel=density.panel, var=sp, from=r/50, to=r/4,
action=density.draw, title="Bandwidth")
在density.panel窗口中增加一个滑块控件,其中var参数指定窗口列表中已有的变量sp,变量的值将由此控件修改。action是修改值时更新用的响应函数。响应函数density.draw以一个窗口变量为输入,并返回可能修改后的窗口变量。
rp.radiogroup添加单选钮,如:
rp.radiogroup(panel=density.panel, var=sp.method,
values=c("normal", "plug-in", "manual"),
title="Bandwidth Selection", action=density.draw)
其中var=sp.method在density.panel列表中定义一个sp.method变量并由此单选钮组选择其取值。
rp.checkbox添加复选框,如:
rp.checkbox(panel=density.panel, var=model,
title="Normal band", action=density.draw)
指定density.panel列表变量model并由此控件控制开关。
rp.doublebutton添加加减按钮,如:
rp.doublebutton(panel=density.panel, var=sp, step=1.02,
log=TRUE, range=c(diff(range(A1203))/50, NA),
title="Bandwidth")
结果是并排的减号和加号,可以控制一个窗口列表变量的增减。var=sp指定要控制的窗口列表变量,step是变化量,log=TRUE指定是用等比方式变化,range给出变换的界限。
R中tcltk包的使用
例子见 http://bioinf.wehi.edu.au/~wettenhall/RTclTkExamples/ 。Tcl/Tk的原始参考资料见 http://www.tkdocs.com/widgets/index.html 和 http://www.tcl.tk/man/tcl8.5/contents.htm 。
要先有一个主窗口,用tktoplevel生成,如:
root <- tktoplevel()
要指定窗口标题,用如:
tktitle(root) <- "tcltk测试"
生成按钮用command指定操作,如:
exit.but <- tkbutton(root,text="退出", command=function() tkdestroy(root))
tkgrid(exit.but) ## 用来摆放按钮
tkfocus(root)
按钮的对应操作是关闭窗口。
提示信息对话框:
res <- tkmessageBox(title="计算程序", message="试验时间数据输入错误!", icon="error",type="ok")
可以用icon="info", icon="warning"。如果type="yesnocancel"结果会有三个按钮, 用default="yes"指定缺省按钮。用as.character(res)查看结果。
用tclVar建立tcl变量,用tclvalue访问其值,如:
done <- tclVar(0) ## 建立tcl变量done, 值为0.
OK.but <- tkbutton(root, text=" OK ", command=function() tclvalue(done)<-1)
按钮的作用是把tcl变量done的值赋值为1. 可以用tclvalue(done)访问这个值,如果是整数应该用as.integer(tclvalue(done))转换。
用tkbind给某个窗口事件规定响应,如:
tkbind(root, "
用tkwait.variable等待tcl变量的值改变,如:
tkwait.variable(done)
用tklabel添加一个标签控件,如:
tkgrid(tklabel(root,text="This is a text label"))
如果需要修改标签内容,可以用tcl变量,如:
labelText <- tclVar("This is a text label")
label1 <- tklabel(root,text=tclvalue(labelText))
tkconfigure(label1,textvariable=labelText) ## 把控件与tcl变量关联。
tkgrid(label1)
ChangeText <- function() tclvalue(labelText) <- "This text label has changed!"
ChangeText.but <- tkbutton(tt,text="Change text label",command=ChangeText)
tkgrid(ChangeText.but)
其中用了tkconfigure把标签控件label1与变量labelText建立了联系。
用tkentry指定文本输入条,如:
tcl.en <- tclVar(1.5)
en <- tkentry(root, textvariable=tcl.en, width=20)
这样可以用as.double(tclvalue(tcl.en))访问输入的值。
用tktext指定文本输入框,如:
txt <- tktext(root, width=20, height=10)
其中宽和高的单位是字符。访问内容如:
s <- as.character(tclvalue(tkget(txt, "0.0", "end"))) ## 全部内容
s <- gsub(",", " ", s) ## 把逗号替换成空格
sc <- textConnection(s) ## 生成输入流
x <- scan(sc)
close(sc)
用tkframe作为容器容纳控件。如:
fr <- tkframe(root, padx=5, pady=5)
其 中padx和pady是在其必须的大小上加富余的空白。用relief和borderwidth指定边界形式,relief有raised, sunken, flat, ridge, solid, groove, 必须指定borderwidth如borderwidth=3才能显示效果。
用tkwidget生成一个一般Tk控件,用type指定类型,如:
fr <- tkwidget(root, type="labelframe", text="选择")
摆放控件用tkpack或tkgrid。tkpack沿上、下、左、右之一边缘摆放,tkgrid可以对准摆放,比如,la1和en1是输入的标签和输入条,la2和en2是另一对,则用
tkgrid(tklabel(root, text="输入部分"), columnspan=2)
tkgrid(la1, en1)
tkgrid(la2, en2)
其中第一个“输入部分”标签占了两列。在tkpack中用padx和pady指定左右和上下的间隙,如:
tkpack(ok.but, side="bottom", padx=10, pady=20)
在MS Windows环境下,为了能单独运行图形界面而不显示R原来的图形界面,可以在程序最后写上:
tcl.exit <- tclVar(0)
tkbind(root, "
tkwait.variable(tcl.exit)
这样在批运行时不至于马上结束。批运行的命令是
\pathToRInstall\bin\rcmd BATCH testtk.r
或
\pathToRInstall\bin\rterm --vanilla <>&1
没有评论:
发表评论