作者cog5566 (刃之56)
看板R_Language
标题Re: [问题] 不会传递 expression 到sub-function
时间Sun Jun 2 11:56:09 2013
※ 引述《Chris7462 (~烤焦面包~)》之铭言:
: ※ 引述《cog5566 (刃之56)》之铭言:
: : [问题类型]:
: : 程式谘询(我想用R 做某件事情,但是我不知道要怎麽用R 写出来)
: : [软体熟悉度]:
: : 入门(写过其他程式,只是对语法不熟悉)
: : [问题叙述]:
: : 以 subsetBy 为例好了 (这是doBy package 的一个function)
: : 这个 function 可以依照组别来筛选 data frame 的资料。
: : 假设我想要写一个 function 会用到 subsetBy
: : 这个 function 的功能是依组别去除 2 倍 SD 之外的资料
: : 问题如下:
: : subsetBy 的第二个参数是要输入一个 expression (应该是吧)
: subsetBy(formula, subset, data = parent.frame(), select, drop=FALSE,
: join=TRUE, ... )
: 第二个参数是 logical 不是 expression,可以看他的说明
: subset logical expression indicating elements or rows to keep: missing values
: taken as false.
: 用他的 example 看一下就知道了
: sbstBy> data(dietox)
: sbstBy> subsetBy(~Evit, Weight < mean(Weight), data=dietox)
: data(dietox)
: dietox$Weight < mean(dietox$Weight)
我想不是 logical 是 logical expression
你看例子的第二个参数是 Weight < mean(Weight)
并不是 dietox$Weight < mean(dietox$Weight)
如果你用
typeof(Weight < mean(Weight))
和
typeof(dietox$Weight < mean(dietox$Weight))
会得到完全不一样的结果
Weight < mean(Weight) 会变成 logical class 会是在 subsetBy 自己的 scope 之内
的事,但是在 subsetBy 之外的时候状况很奇怪。
这也是一个我很不习惯 R 的地方之一。有一些 function 会展现出奇怪的特性,
就是你不知道到底 function 是抓引数的 value 还是 name or expression
譬如说好了
x <- 10
rm('x') 和 rm(x)
有同样的效果
看起来好像没有很奇怪,但是爲什麽 rm(x) 不会变成 rm(10)呢?
下面这个例子就会更奇怪
x <- 10
y <- 'x'
rm(y)
那到底这个时候是什麽情况,到底这时候会抓 rm 的参数 name y 还是 value 'x'?
回到我的问题的例子
subsetBy(~Evit, Weight < mean(Weight), data=dietox)
如果在一般的 function下,而且 Weight 有给予值时,
Weight < mean(Weight) 应该会去抓 Weight 的值来得出 logical class
但是这边等神奇之处就是,Weight 是 dietox 的一个 column,
或是复杂一点的说,是 dietox 这个 data frame 的 environment 里面的变数
他们是在 subsetBy 之内才被组合的。
这样一来,subsetBy 必定会知道 subsetBy 外面被 call 时引数的 expression
而不是值。现在知道这可以用 substitute 来实现,但是我的问题是如果有下一层,
如何将这个 expression 带到下一层?
: : 如
: : subsetBy(~Evit, Weight < mean(Weight), data=dietox)
: : 这个 expression 是筛选资料的算式,其中的变数会对应到 data frame
: : 的 column name
: : 而我想要写一个 function 是
: : sdSubsetFun = function(group, dVar, data)
: : data 是我要操作的 data frame
: : dVar 是要去掉的 2SD 的目标 column name
: : group 是分组的依据 (class 是 formula)
: : 但是我没办法将 dVar 传进去里面的 subsetBy 的第二个参数
: : 程式码如下
: : ######################################################################
: : library('doBy')
: : sdSubsetFun = function(group, dVar, data) {
: : - sdVar = substitute(dVar)
: : # 2SD threshold
: : - subsetThreshold = substitute( (sdVar > (mean(sdVar) - 2*sd(sdVar))) &
: : - (sdVar < (mean(sdVar) + 2*sd(sdVar))) )
: + subsetThreshold = (dVar > (mean(dVar) - 2*sd(dVar))) &
: + (dVar < (mean(dVar) + 2*sd(dVar)))
: : dataOut = subsetBy(group,
: : - subset = eval(subsetThreshold, group, parent.frame()),
: + subset = subsetThreshold,
: : data = data)
: : }
: - 是删除,+ 是新增。这样应该就可以用了 :p
我还是会不行用耶,贴上我的 code
######################################################################
library('doBy')
sdSubsetFun = function(group, dVar, data) {
# 2SD threshold
subsetThreshold = (dVar > (mean(dVar) - 2*sd(dVar))) &
(dVar < (mean(dVar) + 2*sd(dVar)))
dataOut = subsetBy(group,
subset = subsetThreshold,
data = data)
}
x = rep(c('a','b','c'), 50)
y = 1:150
tData = data.frame(aa = x, bb = y)
subData = sdSubsetFun(~aa, bb, tData)
######################################################################
Error in sdSubsetFun(~aa, bb, tData) : object 'bb' not found
######################################################################
其实很显而易见,在 evaluate dVar 的时候会在 local environment 找不到值,
因为 dynamic scope 的关系,它会去 global environment 找,但也会找不到。
所以他会再找 bb 的value,但是根本就没有 bb 这个变数,bb是tData的 column name
所以最後他会说 bb 找不到。
还是说我什麽地方弄错了?可能有小细节没有注意到。
: : # Create Data
: : aa = rep(c('a','b','c'), 50)
: : bb = 1:150
: : tData = data.frame(aa,bb)
: : subData = sdSubsetFun(~aa, bb, tData)
: : ######################################################################
: : 错误讯息为:
: : Error in eval(subsetThreshold, group, parent.frame()) :
: : object 'subsetThreshold' not found
: : 也就是说,里面的 subsetBy 都不会抓我的 subsetThreshold 的值,
: : 都还是会抓 subsetThreshold 自己本身的 expression。
: : 要怎麽做才会让他抓到 subsetThreshold 的值呢?
--
※ 发信站: 批踢踢实业坊(ptt.cc)
◆ From: 139.184.222.89