在下面的可重现的示例中,我试图动态构建一个ggplot2
函数调用,以便能够容纳未知数量的混合分布组件。该代码生成此错误消息:Error in parse(text = g) : <text>:8:0: unexpected end of input
。代码有什么问题? (我知道预先计算绘图数据的方法,将其存储在数据框中,将其融合并提供给ggplot2
。我也想探索下面的选项。)谢谢!
library(ggplot2)
library(scales)
library(RColorBrewer)
library(mixtools)
NUM_COMPONENTS <- 2
set.seed(12345) # for reproducibility
data(diamonds, package='ggplot2') # use built-in data
myData <- diamonds$price
calc.component <- function(x, lambda, mu, sigma) {
lambda * dnorm(x, mean = mu, sd = sigma)
}
overlayHistDensity <- function(data, func) {
# extract 'k' components from mixed distribution 'data'
mix <- normalmixEM(data, k = NUM_COMPONENTS,
maxit = 100, epsilon = 0.01)
summary(mix)
DISTRIB_COLORS <-
suppressWarnings(brewer.pal(NUM_COMPONENTS, "Set1"))
# plot histogram, empirical and fitted densities
g <- "ggplot(data) +\n"
for (i in seq(length(mix$lambda))) {
args <- paste0("args.", i)
assign(args, list(lambda = mix$lambda[i], mu = mix$mu[i],
sigma = mix$sigma[i]))
g <- paste0(g,
"stat_function(fun = func, args = ",
args,
", aes(color = ",
DISTRIB_COLORS[i], ")) +\n")
}
tailStr <-
"geom_line(aes(y = ..density..,colour = 'Empirical'),stat = 'density') +
geom_histogram(aes(y = ..density..), alpha = 0.4) +
scale_colour_manual(name = '', values = c('red', 'blue')) +
theme(legend.position = 'top', legend.direction = 'horizontal')"
g <- paste0(g, tailStr)
gr <- eval(parse(text = g))
return (gr)
}
overlayHistDensity(log10(myData), 'calc.component')
答案 0 :(得分:3)
只要你意识到你正在努力解决这个问题......
如果在解析之前查看g
的值,则为
ggplot(data) +
stat_function(fun = func, args = args.1, aes(color = #E41A1C)) +
stat_function(fun = func, args = args.2, aes(color = #377EB8)) +
geom_line(aes(y = ..density..,colour = 'Empirical'),stat = 'density') +
geom_histogram(aes(y = ..density..), alpha = 0.4) +
scale_colour_manual(name = '', values = c('red', 'blue')) +
theme(legend.position = 'top', legend.direction = 'horizontal')
通常unexpected end of input
消息来自不平衡的引号或括号,但你(显然)没有在这里遇到这个问题。问题在于颜色规范。文字十六进制颜色应指定为字符串
ggplot(data) +
stat_function(fun = func, args = args.1, aes(color = "#E41A1C")) +
stat_function(fun = func, args = args.2, aes(color = "#377EB8")) +
geom_line(aes(y = ..density..,colour = 'Empirical'),stat = 'density') +
geom_histogram(aes(y = ..density..), alpha = 0.4) +
scale_colour_manual(name = '', values = c('red', 'blue')) +
theme(legend.position = 'top', legend.direction = 'horizontal')
如果没有引号,散列是注释字符,其余行(特别是右括号)不包括在内,并且给出了错误。 (注意SO在第一个代码片段中突出显示的语法。)
那就是说,我认为如果没有eval(parse())
方法,你可以得到你想要的东西。特别是,请查看aes_string
,它允许通过字符串变量的值来指定哪个变量用作美学,并添加stat
s或geom
s的列表(可以具有使用lapply
创建的未预先指定的长度。此外,您似乎指定了文字颜色,然后将它们映射到红色和蓝色;你想要scale_colour_identity
吗?所有这些(最后一段)是更多的代码审查,而不是你实际问的。
答案 1 :(得分:3)
你有几个问题:
ggplot
的数据参数必须是data.frame,而不是vector #
开头的aes(x = )
映射aes
这应该有效:
overlayHistDensity <- function(data, func) {
# extract 'k' components from mixed distribution 'data'
mix <- normalmixEM(data, k = NUM_COMPONENTS,
maxit = 100, epsilon = 0.01)
summary(mix)
DISTRIB_COLORS <-
suppressWarnings(brewer.pal(NUM_COMPONENTS, "Set1"))
# plot histogram, empirical and fitted densities
g <- "ggplot(as.data.frame(data), aes(x = data)) +\n"
for (i in seq(length(mix$lambda))) {
args <- paste0("args.", i)
assign(args, list(lambda = mix$lambda[i], mu = mix$mu[i],
sigma = mix$sigma[i]))
g <- paste0(g,
"stat_function(fun = func, args = ",
args,
", color = '",
DISTRIB_COLORS[i], "') +\n")
}
tailStr <-
"geom_line(aes(y = ..density..,colour = 'Empirical'),stat = 'density') +
geom_histogram(aes(y = ..density..), alpha = 0.4) +
scale_colour_manual(name = '', values = c('red', 'blue')) +
theme(legend.position = 'top', legend.direction = 'horizontal')"
g <- paste0(g, tailStr)
gr <- eval(parse(text = g))
return (gr)
}
像Brian一样,我将以2条评论结束:
这是标准调试,您不需要SO帖子。它本质上是几个语法错误和几个小错误。我将您的代码放在函数之外并在最后的g <- paste0
行中运行,并将g
输出放在代码窗口中并查找问题。尝试编写首先在函数之外工作的代码,然后将其放在函数中。
借调Brian的评论,更自然的方法是不使用eval(parse())
以及所有这些粘贴。相反,请使用aes_string
,融化您的数据,以便您可以根据分组变量使用一次stat_function
调用。