好的,我正在上这堂课,其中一位学生发布了一个关于密谋使用的问题。事实证明,她并不需要为她的情节而烦恼,但我和你一起玩,看看你如何使用它。
所以使用with base plotting很有意思,我可以得到很酷的情节。
然后我决定尝试将它与ggplot一起使用。特别是qplot。现在我知道这不是这样做的方式,但我很想知道会发生什么。
所以我这样做了:
我创建了一个小数据框 - mydf
> mydf
x y year
1 6 24 2004
2 22 28 2004
3 44 16 2004
4 40 47 2003
5 50 23 2002
6 49 48 2003
7 2 21 2004
8 3 12 2002
9 19 11 2003
10 29 25 2002
所以正确的方法是:
qplot(x,y,data = mydf)
显然它很有效。但我很想知道发生了什么,所以我做了这个
with(mydf,qplot(x,y))
我真的没想到它会起作用,但事实确实如此。凉爽
然后我尝试了方面。所以这样做是正确的。
qplot(x,y, facets = .~ year,data = mydf)
但这会引发错误。
> with(mydf,qplot(x,y, facets = .~ year))
Error in FUN("year"[[1L]], ...) : object 'year' not found
我发现奇怪的是,qplot可以访问mydf $ x和mydf $ y,而尝试访问face in face则会抛出错误。
我认为这是与环境有关的问题。例如,我可以这样做:
the_years <- mydf$year
with(mydf,qplot(x,y, facets = .~ the_years))
它很好。因此,如果我在全局环境中有一个变量,那么就可以访问它。
但是这个
with(mydf,qplot(x,y, facets = .~ mydf$year))
Error in FUN(c("mydf", "year")[[2L]], ...) : object 'year' not found
会抛出错误,即使这也是在全局环境中。这种错误类似于将mydf和year拆分为传递给函数的两个不同参数。
据我了解,创建一个环境然后在该环境中评估表达式
所以这是有效的
> with(mydf,{new_years <- year;print(new_years)})
[1] 2004 2004 2004 2003 2002 2003 2004 2002 2003 2002
Levels: 2002 2003 2004
我有点希望这会奏效。在with环境中创建一个新变量。
> with(mydf,{new_years <- year; qplot(x,y, facets = .~ new_years)})
Error in FUN("new_years"[[1L]], ...) : object 'new_years' not found
但qplot仍然没有看到它
所以我希望比我聪明的人能告诉我发生了什么。
我知道这是有史以来最奇怪的问题之一。正确答案是:&#34;不要这样做&#34;。 :)
如果qplot在我以这种方式使用x和y时遭到轰炸,我将非常高兴。但是基本情节部分中的qplot可以访问mydf $ x和mydf $ y,这似乎很奇怪。但是mtf $ year并没有在facets电话中找到。
欢迎任何想法。
答案 0 :(得分:2)
和自己说话。对此感到抱歉,但这真让我烦恼。 :)
以下是我的想法。这是来自github的qplot的代码。 https://github.com/hadley/ggplot2/blob/master/R/quick-plot.r
if (missing(data)) {
# If data not explicitly specified, will be pulled from workspace
data <- data.frame()
# Faceting variables must be in a data frame, so pull those out
facetvars <- all.vars(facets)
facetvars <- facetvars[facetvars != "."]
names(facetvars) <- facetvars
facetsdf <- as.data.frame(lapply(facetvars, get))
if (nrow(facetsdf)) data <- facetsdf
}
我的想法是,如果没有指定数据框,那么代码会尝试从构面中获取信息。
如果没有创建数据框中传递的数据 - 称为数据
facetvars是从all.vars(facets)创建的。
all.vars返回一个字符向量,其中包含表达式或调用中出现的所有名称。 http://www.inside-r.org/r-doc/base/all.vars
这里有一些例子
> all.vars(.~ mydf)
[1] "." "mydf"
> all.vars(.~ mydf$year)
[1] "." "mydf" "year"
> all.vars(.~ year)
[1] "." "year"
下一行摆脱&#39;。&#39;
然后它使用名称来设置名称,然后它尝试创建一个数据框&#34;&#34;得到&#34;来自环境的信息使用get()函数和KABOOM!
以下是我浏览代码时的结果
> facetvars <- all.vars(.~ year)
> facetvars
[1] "." "year"
> facetvars <- facetvars[facetvars != "."]
> facetvars
[1] "year"
> names(facetvars) <- facetvars
> facetvars
year
"year"
> facetsdf <- as.data.frame(lapply(facetvars, get))
Error in FUN("year"[[1L]], ...) : object 'year' not found
这是在文件中调用get的唯一地方。所以它正在寻找错误的环境来构建新的facetsdf数据框架,并且没有办法改变环境 - 至少很容易。没有&#34;年&#34;在全球环境中。 &#34;一年&#34;确实存在于&#34;与&#34;环境,但qplot看不到那里。
我不确定qplot的环境是什么样的。我原本认为这将是环境,但似乎并非如此。无论哪种方式,它都会在环境树中查找&#34;年&#34;但从来没有找到它。 &#34;&#34;的环境在另一个分支上。
这是另一个例子。同样的问题 - 没有&#34;年&#34;在qplot正在查找的任何环境中。
> facetvars <- all.vars(.~ mydf$year)
> facetvars
[1] "." "mydf" "year"
> facetvars <- facetvars[facetvars != "."]
> facetvars
[1] "mydf" "year"
> names(facetvars) <- facetvars
> facetvars
mydf year
"mydf" "year"
> facetsdf <- as.data.frame(lapply(facetvars, get))
Error in FUN(c("mydf", "year")[[2L]], ...) : object 'year' not found
它起作用的例子
> facetvars <- all.vars(.~ the_years)
> facetvars
[1] "." "the_years"
> facetvars <- facetvars[facetvars != "."]
> facetvars
[1] "the_years"
> names(facetvars) <- facetvars
> facetvars
the_years
"the_years"
> facetsdf <- as.data.frame(lapply(facetvars, get))
> facetsdf
the_years
1 2004
2 2004
3 2004
4 2003
5 2002
6 2003
7 2004
8 2002
9 2003
10 2002
所以现在它可以找到&#34; the_years&#34;在全球环境中。它可以面对这个变量。
另一个例子。
> facetvars <- all.vars(.~ mydf)
> facetvars
[1] "." "mydf"
> facetvars <- facetvars[facetvars != "."]
> facetvars
[1] "mydf"
> names(facetvars) <- facetvars
> facetvars
mydf
"mydf"
> facetsdf <- as.data.frame(lapply(facetvars, get))
> facetsdf
mydf.x mydf.y mydf.year
1 6 24 2004
2 22 28 2004
3 44 16 2004
4 40 47 2003
5 50 23 2002
6 49 48 2003
7 2 21 2004
8 3 12 2002
9 19 11 2003
10 29 25 2002
现在这一次&#34; mydf&#34;找到了 - 但qplot不知道如何处理它。
with(mydf,qplot(x,y, facets = . ~ mydf))
Error in layout_base(data, cols, drop = drop) :
At least one layer must contain all variables used for faceting
所以,这是我对自己问题的最佳答案。当没有数据传入时,qplot只尝试从不同的环境中获取get(),此时,如果存在facet,那么它会尝试使用facet中的信息来创建数据框,这就是代码炸弹的时候。
稍后编辑以添加: 是的,还在跟自己说话。 :)事实证明,修复此行为需要做的就是对quick-plot.R(qplot的源代码)的源代码进行微小的更改
你所要做的就是搬家
env <- parent.frame()
到代码中的某个位置然后在<-p>中的quick-plot.R中更改第97行
facetsdf <- as.data.frame(lapply(facetvars, get))
到
facetsdf <- as.data.frame(lapply(facetvars, function(x) {get(x,env)}))
然后将按预期工作。