使用名为' 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;)),但无法找到解决方案。
答案 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
及其所有结果列位于本地范围内,即列state
和measure
优先于全局环境中的对象state
和measure
。因此,对于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
函数调用的本地框架中找不到Measure
和subset
,解释器将继续搜索环境直到它第一次遇到这些对象(在这种情况下,它在全局环境中找到它们)。这就是为什么当我在你的函数State
中将参数更改为Measure
和lowest
(并在函数体中进行了相应的更改)时,它产生了所需的结果 - 实际上你可以改变它们几乎任何东西,只要名称不与data
的列名冲突,但将他们的第一个字母大写是一个快速修复。