子集函数不评估参数

时间:2014-07-23 14:22:27

标签: r function subset argument-passing

使用名为' data'的以下数据框,我可以直接将值分配给两个变量,' state'和'衡量',并确定子集中得分最低的学校:

创建数据框'数据':

school<-c("NYU", "BYU", "USC", "FIT", "Oswego","UCLA","USF","Columbia")
state<-c("NY","UT","CA","NY","NY","CA", "CA","NY")
measure<-c("MSAT","MSAT","GPA","MSAT","MSAT","GPA","GPA","GPA")
score<-c(590, 490, 2.9, 759, 550, 1.2, 3.1, 3.2)
data<-data.frame(school,state, measure,score)

状态&#39;上的子集和&#39;衡量&#39;:

answer<-subset(data,subset=(state=="NY" & measure=="MSAT"))
order.answer<-order(answer$score,answer$school) #answer$school is tie-breaker
answer1<-as.matrix(answer[order.answer,])
answer1[1,1]

这是正确答案:

[1] "Oswego"

我的问题是,当我创建一个函数来完成同样的事情时,我得到一个不正确的结果:

lowest <- function(state, measure){
    answer<-subset(data,subset=(state==state & measure==measure))
    order.answer<-order(answer$score,answer$school)
    answer1<-as.matrix(answer[order.answer,])
    answer1[1,1]
  }

lowest("NY","MSAT")

答案不正确:

[1] "UCLA"

问题似乎是变量&#39;状态&#39;和&#39;衡量&#39;不要接受论证的价值观&#34; NY&#34;和&#34; MSAT&#34;在函数的子集行中。我已经尝试过&#39; =&#39;而不是&#39; ==&#39;并尝试了子集(数据,子集=(状态==&#34;状态&#34;&amp;测量==&#34;测量&#34;)),但无法找到解决方案。

1 个答案:

答案 0 :(得分:2)

您的函数调用中似乎存在一些问题,因为您的函数参数与数据列相同,因为这可以正常工作

lowest <- function(State, Measure){
  answer<-subset(data,subset=(state==State & measure==Measure))
  order.answer<-order(answer$score,answer$school)
  answer1<-as.matrix(answer[order.answer,])
  answer1[1,1]
}
##
> lowest("NY","MSAT")
[1] "Oswego"

更新:仔细考虑之后,我想我可以提供一些关于内部情况的更多细节。请注意,您的第一个(手动)子集在上面正确工作:

> subset(data,subset=(state=="NY" & measure=="MSAT"))
  school state measure score
1    NYU    NY    MSAT   590
4    FIT    NY    MSAT   759
5 Oswego    NY    MSAT   550

但是,请注意,如果我们在全局环境state <- "NY"measure <- "MSAT"中创建两个对象,则无效

state <- "NY"
measure <- "MSAT" 
> subset(data,state==state & measure==measure)
    school state measure score
1      NYU    NY    MSAT 590.0
2      BYU    UT    MSAT 490.0
3      USC    CA     GPA   2.9
4      FIT    NY    MSAT 759.0
5   Oswego    NY    MSAT 550.0
6     UCLA    CA     GPA   1.2
7      USF    CA     GPA   3.1
8 Columbia    NY     GPA   3.2

原因(我相信)与R的范围解析机制及其在功能中的运作方式有关。当在R中调用一个函数时,这个函数调用会创建一个(临时的?)环境,其中该函数中的对象驻留在本地框架中,即它们的优先级在某种意义上,如果你有一个变量x全局环境和定义为foo <- function(x){do something interesting to x}的函数,do something interesting通过参数foo作用于传递到x的对象,全局环境中的对象x。但是,R使用动态范围,这意味着如果找不到本地帧中引用的对象,则解释器将递归搜索帧/环境的层次结构,直到找到所引用的对象。因此,如果您foo <- function(x){do something interesting to x}代替foo(z){do something interesting to x},但仍然在全局环境中定义x,而不是导致错误,则该函数将搜索通过调用堆栈直到它找到对象x到&#34;做一些有趣的事情&#34;至。

在上面的示例中,subset(data,state==state & measure==measure)未产生预期结果且subset(data,state=="NY & measure=="MSAT")所做的原因是因为在subset(data, ...)函数调用中data及其所有结果列位于本地范围内,即列statemeasure优先于全局环境中的对象statemeasure。因此,对于state==state & measure==measure的每一行,子集条件TRUE评估为data,因此&#34;子集&#34;返回的是data的全部内容。现在,如果我们这样做

State <- "NY"
Measure <- "MSAT"
> subset(data, state==State & measure==Measure)
  school state measure score
1    NYU    NY    MSAT   590
4    FIT    NY    MSAT   759
5 Oswego    NY    MSAT   550

这很好用,因为在State函数调用的本地框架中找不到Measuresubset,解释器将继续搜索环境直到它第一次遇到这些对象(在这种情况下,它在全局环境中找到它们)。这就是为什么当我在你的函数State中将参数更改为Measurelowest(并在函数体中进行了相应的更改)时,它产生了所需的结果 - 实际上你可以改变它们几乎任何东西,只要名称不与data的列名冲突,但将他们的第一个字母大写是一个快速修复。