R 中按值传递

发布于 2024-11-29 10:11:08 字数 790 浏览 1 评论 0原文

当尝试调用 grid.arrange 将多个图放在同一个 ggplot2 图上时,我首先构建一个我想要的图的列表。然后,我构建相应的参数列表来调用 grid.arrange,如所解释的 在上一个问题中。这是我的代码(我的数据框称为 manip):

args.list <- NULL;
plot.list <- NULL;
for (m in names(manip[2:10])) {
  plot.list <- c(plot.list, list(qplot(manip$side, y=manip[,m],ylab=m))
}
args.list <- c(plot.list, 1, 9)
names(args.list) <- c(names(manip)[2:10], list("nrow","ncol"))
do.call(grid.arrange, args.list)

这有效,只是 9 个图完全相同!经过检查发现,数据始终是m=10对应的数据。所以我的猜测是 m 的值不是在循环中分配的,而是稍后评估的。但是,标签 ylab=m 分配正确,并且对于所有图表而言都不同。

所以我真的不明白有什么区别以及解释器如何选择何时评估图的 m 。有人可以解释一下吗?

When trying to call grid.arrange to put multiple plots on a same ggplot2 graph, I first build a list of the plots I want. Then I build the corresponding argument list to call grid.arrange, as was explained in a previous question. This is my code (my dataframe is called manip):

args.list <- NULL;
plot.list <- NULL;
for (m in names(manip[2:10])) {
  plot.list <- c(plot.list, list(qplot(manip$side, y=manip[,m],ylab=m))
}
args.list <- c(plot.list, 1, 9)
names(args.list) <- c(names(manip)[2:10], list("nrow","ncol"))
do.call(grid.arrange, args.list)

This works, except that the 9 graphs are exactly the same! After checking, it turns out that the data is always the one corresponding to m=10. So my guess was that the value of m is not assigned in the loop, but evaluated later. However, the label ylab=m is assigned correctly and is different for all the graphs.

So I don't really get what the difference is and how the interpreter chooses when to evaluate m for the plots. Can someone explain?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

对你而言 2024-12-06 10:11:08

该行为是由于 R 的惰性求值所致。

这是一个最小(?)示例:

d <- 1:3

args.list <- NULL;
plot.list <- NULL;
for (m in 1:3) {
 plot.list <- c(plot.list, list(qplot(d[m], d[m], ylab=letters[m])))
}

args.list <- c(plot.list, nrow=1, ncol=3)
do.call(grid.arrange, args.list)

在本例中,d[m] 在调用 do.call。所以所有面板的 m 都是 3。

这里有一个解决方法:

d <- 1:3

args.list <- NULL;
plot.list <- NULL;
for (m in 1:3) {
  plot.list <- c(plot.list,
    list(qplot(d, d, data=data.frame(d=d[m]), ylab=letters[m])))
}

args.list <- c(plot.list, nrow=1, ncol=3)
do.call(grid.arrange, args.list)

在这种情况下,在调用 qplot 时计算 d[m],并存储 d[m]在 qplot 的输出对象中。

因此,简单的解决方案是将数据传递给 qplot()ggplot()

The behavior is due to the lazy evaluation of R.

Here is a minimal(?) example:

d <- 1:3

args.list <- NULL;
plot.list <- NULL;
for (m in 1:3) {
 plot.list <- c(plot.list, list(qplot(d[m], d[m], ylab=letters[m])))
}

args.list <- c(plot.list, nrow=1, ncol=3)
do.call(grid.arrange, args.list)

in this case, d[m] is evaluated at the call of do.call. so m is 3 for all panel.

here is a workaround:

d <- 1:3

args.list <- NULL;
plot.list <- NULL;
for (m in 1:3) {
  plot.list <- c(plot.list,
    list(qplot(d, d, data=data.frame(d=d[m]), ylab=letters[m])))
}

args.list <- c(plot.list, nrow=1, ncol=3)
do.call(grid.arrange, args.list)

in this case, d[m] is evaluated at the call of qplot, and the d[m] is stored in the output object of qplot.

so, the simple solution is to pass data to qplot() or ggplot().

失与倦" 2024-12-06 10:11:08

我将首先回答您的问题,然后使用分面图展示替代方案。

编辑

以下经过简化的代码似乎可以工作:

library(gridExtra)
manip <- mtcars
plot.list <- lapply(2:11, 
                    function(x)qplot(manip$mpg, y=manip[, x], 
                    ylab=names(manip)[x]))
do.call(grid.arrange, c(plot.list, nrow=10))

它产生了这个丑陋的情节:
在此处输入图像描述


我知道,在不了解您的目标的情况下尝试提供建议是危险的。尽管如此,您是否考虑过在情节中使用多方面?

下面的代码要简单得多,执行 quiker 并生成一个更容易解释的图表:

library(reshape2)
manip <- mtcars
mmanip <- melt(manip, id.vars="mpg")
str(mmanip)
ggplot(mmanip, aes(x=mpg, y=value)) + 
    geom_point(stat="identity") + 
    facet_grid(.~variable, scales="free")

在此处输入图像描述

I will first answer your question and then show an alternative using a facet plot.

Edited

The following, much simplified, code seems to work:

library(gridExtra)
manip <- mtcars
plot.list <- lapply(2:11, 
                    function(x)qplot(manip$mpg, y=manip[, x], 
                    ylab=names(manip)[x]))
do.call(grid.arrange, c(plot.list, nrow=10))

It produces this ugly plot:
enter image description here


Without knowing your objectives, it is dangerous to try and give advice, I know. Nonetheless, have you considered using facets for your plot instead?

The following code is much simpler, executes quiker and produces a graph that is easier to interpret:

library(reshape2)
manip <- mtcars
mmanip <- melt(manip, id.vars="mpg")
str(mmanip)
ggplot(mmanip, aes(x=mpg, y=value)) + 
    geom_point(stat="identity") + 
    facet_grid(.~variable, scales="free")

enter image description here

吾家有女初长成 2024-12-06 10:11:08

也许融化数据并使用分面会更好?

library(ggplot2)
manip <- data.frame(car = row.names(mtcars), mtcars)
manip.m  <- melt(manip)
qplot(car, value, data = manip.m) + facet_wrap(~variable, scales = "free_y")

它需要在 xlab 中进行一些打磨

last_plot() + opts(axis.text.x = theme_text(angle = 90))

在此处输入图像描述

HTH

Perhaps it would be better to melt then data and use faceting?

library(ggplot2)
manip <- data.frame(car = row.names(mtcars), mtcars)
manip.m  <- melt(manip)
qplot(car, value, data = manip.m) + facet_wrap(~variable, scales = "free_y")

It need some polishing in the xlab

last_plot() + opts(axis.text.x = theme_text(angle = 90))

enter image description here

HTH

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文