R函数的最后一行阻止绘图
last line of an R function prevent the plotting
我真的很想知道为什么当我在函数 foo1
中保留最后一行 (sigma
) 时,我的 plot
调用停止工作但是当我删除 foo2
plot
调用正常吗?!
注意:我的理解是绘图应该显示在函数的任何地方,如:
foo3 <- function(x = 1:3){; plot(x); return(x); }; foo3()
我需要保留最后一行但我还需要绘图,这个可以修复吗?
library(lme4)
library(emmeans)
h <- read.csv('https://raw.githubusercontent.com/hkil/m/master/h.csv')
h$year <- as.factor(h$year)
m <- lmer(scale~ year*group + (1|stid), data = h)
foo1 <- function(fit, plot = T){
vc <- VarCorr(fit)
f <- as.formula(bquote(pairwise ~ .(terms(fit)[[3]])))
ems <- emmeans(fit, f, infer = c(T, T))
if(plot) plot(ems)
## Why having this line prevents plotting?
sigma <- sqrt(sum(as.numeric(c(attr(vc[[1]], "stddev"), attr(vc, "sc")))^2))
}
###### EXAMPLE: Will NOT plot !!!
foo1(m, plot = T)
但是只需删除 foo1
的最后一行,绘图就可以正常工作了!
foo2 <- function(fit, plot = T){
f <- as.formula(bquote(pairwise ~ .(terms(fit)[[3]])))
ems <- emmeans(fit, f, infer = c(T, T))
if(plot) plot(ems)
}
###### EXAMPLE: NOW plots fine !!!
foo2(m, plot = T)
好吧,这是有道理的,因为在 foo2
中,plot
是函数中的最后一个命令,它 returns 而在 foo1
中并非如此。
如果您想 plot
然后做一些额外的计算,一个简单的方法是在函数中 print
它。
foo1 <- function(fit, plot = T){
vc <- VarCorr(fit)
f <- as.formula(bquote(pairwise ~ .(terms(fit)[[3]])))
ems <- emmeans(fit, f, infer = c(T, T))
if(plot) print(plot(ems))
sigma <- sqrt(sum(as.numeric(c(attr(vc[[1]], "stddev"), attr(vc, "sc")))^2))
}
那么如果你 运行 foo1
x <- foo1(m, plot = T)
x
#[1] 126.61
它 returns sigma
函数的值,因为我们正在使用 print
它 plots
它也是如此。
意外行为的根本原因是 emmeans
使用 ggplot2
作为绘图方法。您可以检查函数 emmeans:::.plot.srg
的代码。这就是为什么您可以将绘图存储在一个对象中 (p
) 并且 print
它:
foo1 <- function(fit, plot=TRUE) {
vc <- VarCorr(fit)
f <- as.formula(bquote(pairwise ~ .(terms(fit)[[3]])))
ems <- emmeans(fit, f, infer=c(TRUE, TRUE))
sigma <- sqrt(sum(as.numeric(c(attr(vc[[1]], "stddev"), attr(vc, "sc")))^2))
p <- plot(ems)
if(plot) print(p)
return(sigma)
}
foo1(m, plot=TRUE) ## plots
# [1] 126.6106
凭直觉,我们期望您的 foo3 <- function(x = 1:3){; plot(x); return(x); }; foo3()
示例中的行为:
foo2 <- function(x, plot=TRUE) {
y <- seq_len(x)^2
if(plot) plot(seq_len(x), y)
return(y)
}
foo2(20) ## plots
# [1] 1 4 9 16 25 36 49 64 81 100 121 144 169
# [14] 196 225 256 289 324 361 400
但是当使用 ggplot
时,它的工作方式不同。当我们不存储 "ggplot"
对象时,下一行将 "overwrite" 绘图。
library(ggplot2)
foo3a <- function(x, plot=TRUE) {
y <- seq_len(x)^2
if(plot) ggplot(mapping=aes(seq_len(x), y)) + geom_point()
return(y) ## try to comment/un-comment this line
}
foo3a(20) ## won't plot, just output of y (depending on `return`)
因此我们实际上必须 print
"ggplot"
对象(我通过将绘图存储在函数 foo3b
的 p
中来显示),如果它不是最后一个函数行。
foo3b <- function(x, plot=TRUE) {
y <- seq_len(x)^2
p <- ggplot(mapping=aes(seq_len(x), y)) + geom_point()
if(plot) print(p)
return(y) ## try to comment/un-comment this line (works in both cases)
}
foo3b(20) ## plots
# [1] 1 4 9 16 25 36 49 64 81 100 121 144 169
# [14] 196 225 256 289 324 361 400
请注意,使用 return
也很有用。
我真的很想知道为什么当我在函数 foo1
中保留最后一行 (sigma
) 时,我的 plot
调用停止工作但是当我删除 foo2
plot
调用正常吗?!
注意:我的理解是绘图应该显示在函数的任何地方,如:
foo3 <- function(x = 1:3){; plot(x); return(x); }; foo3()
我需要保留最后一行但我还需要绘图,这个可以修复吗?
library(lme4)
library(emmeans)
h <- read.csv('https://raw.githubusercontent.com/hkil/m/master/h.csv')
h$year <- as.factor(h$year)
m <- lmer(scale~ year*group + (1|stid), data = h)
foo1 <- function(fit, plot = T){
vc <- VarCorr(fit)
f <- as.formula(bquote(pairwise ~ .(terms(fit)[[3]])))
ems <- emmeans(fit, f, infer = c(T, T))
if(plot) plot(ems)
## Why having this line prevents plotting?
sigma <- sqrt(sum(as.numeric(c(attr(vc[[1]], "stddev"), attr(vc, "sc")))^2))
}
###### EXAMPLE: Will NOT plot !!!
foo1(m, plot = T)
但是只需删除 foo1
的最后一行,绘图就可以正常工作了!
foo2 <- function(fit, plot = T){
f <- as.formula(bquote(pairwise ~ .(terms(fit)[[3]])))
ems <- emmeans(fit, f, infer = c(T, T))
if(plot) plot(ems)
}
###### EXAMPLE: NOW plots fine !!!
foo2(m, plot = T)
好吧,这是有道理的,因为在 foo2
中,plot
是函数中的最后一个命令,它 returns 而在 foo1
中并非如此。
如果您想 plot
然后做一些额外的计算,一个简单的方法是在函数中 print
它。
foo1 <- function(fit, plot = T){
vc <- VarCorr(fit)
f <- as.formula(bquote(pairwise ~ .(terms(fit)[[3]])))
ems <- emmeans(fit, f, infer = c(T, T))
if(plot) print(plot(ems))
sigma <- sqrt(sum(as.numeric(c(attr(vc[[1]], "stddev"), attr(vc, "sc")))^2))
}
那么如果你 运行 foo1
x <- foo1(m, plot = T)
x
#[1] 126.61
它 returns sigma
函数的值,因为我们正在使用 print
它 plots
它也是如此。
意外行为的根本原因是 emmeans
使用 ggplot2
作为绘图方法。您可以检查函数 emmeans:::.plot.srg
的代码。这就是为什么您可以将绘图存储在一个对象中 (p
) 并且 print
它:
foo1 <- function(fit, plot=TRUE) {
vc <- VarCorr(fit)
f <- as.formula(bquote(pairwise ~ .(terms(fit)[[3]])))
ems <- emmeans(fit, f, infer=c(TRUE, TRUE))
sigma <- sqrt(sum(as.numeric(c(attr(vc[[1]], "stddev"), attr(vc, "sc")))^2))
p <- plot(ems)
if(plot) print(p)
return(sigma)
}
foo1(m, plot=TRUE) ## plots
# [1] 126.6106
凭直觉,我们期望您的 foo3 <- function(x = 1:3){; plot(x); return(x); }; foo3()
示例中的行为:
foo2 <- function(x, plot=TRUE) {
y <- seq_len(x)^2
if(plot) plot(seq_len(x), y)
return(y)
}
foo2(20) ## plots
# [1] 1 4 9 16 25 36 49 64 81 100 121 144 169
# [14] 196 225 256 289 324 361 400
但是当使用 ggplot
时,它的工作方式不同。当我们不存储 "ggplot"
对象时,下一行将 "overwrite" 绘图。
library(ggplot2)
foo3a <- function(x, plot=TRUE) {
y <- seq_len(x)^2
if(plot) ggplot(mapping=aes(seq_len(x), y)) + geom_point()
return(y) ## try to comment/un-comment this line
}
foo3a(20) ## won't plot, just output of y (depending on `return`)
因此我们实际上必须 print
"ggplot"
对象(我通过将绘图存储在函数 foo3b
的 p
中来显示),如果它不是最后一个函数行。
foo3b <- function(x, plot=TRUE) {
y <- seq_len(x)^2
p <- ggplot(mapping=aes(seq_len(x), y)) + geom_point()
if(plot) print(p)
return(y) ## try to comment/un-comment this line (works in both cases)
}
foo3b(20) ## plots
# [1] 1 4 9 16 25 36 49 64 81 100 121 144 169
# [14] 196 225 256 289 324 361 400
请注意,使用 return
也很有用。