2017-02-11 27 views
1

我想在函数里面使用ggplot,但是我无法产生 这个图。具体而言,我想确定图 将从函数调用中使用facet_grid()。这是我的数据:函数里面不能使用ggplot分面

mydf <- data.frame(
    group = rep(c("g1", "g2"), each = 16, times = 1), 
    cluster = rep(c("c1", "c2"), each = 8, times = 2), 
    score1 = c(rnorm(n = 16, mean = 10, sd = 10), rnorm(n = 16, mean = 18, sd = 10)), 
    score2 = c(rnorm(n = 16, mean = 50, sd = 10), rnorm(n = 16, mean = 33, sd = 10)) 
) 

下面是函数:

myFunc <- function(data, group = NULL, group2, var1, var2) { 

    # So we don't need quotation marks in function call 
    arguments <- as.list(match.call()) 
    var1 = eval(arguments$var1, data) 
    var2 = eval(arguments$var2, data) 
    group2 = eval(arguments$cluster, data) 
    grouping = eval(arguments$group, data) 

    # Make this graph if no faceting needed 
    if (length(grouping) == 0) { 

    means <- aggregate(cbind(var1, var2) ~ group2, FUN = mean, data = data) 

    ggplot(data, aes(x = var1, y = var2, color = group2, label = group2)) + 
    stat_ellipse(type = "norm", show.legend = FALSE, geom = "polygon", alpha = 0.1) + 
    geom_text(alpha = 0.5, show.legend = FALSE) + 
    geom_text(data = means, aes(x = var1, y = var2, color = group2)) 


    # Use faceting 
    } else if (length(grouping) > 0) { 

    means <- aggregate(cbind(var1, var2) ~ grouping + group2, FUN = mean, data = data) 

    # Plot 
    ggplot(data, aes(x = var1, y = var2, color = group2, label = group2)) + 
    stat_ellipse(type = "norm", show.legend = FALSE, geom = "polygon", alpha = 0.1) + 
    geom_text(alpha = 0.5, show.legend = FALSE) + 
    geom_text(data = means, aes(x = var1, y = var2, color = group2)) + 
    facet_grid(. ~ grouping) 

    } 

} 

我打电话,像这样的功能:

myFunc(data = mydf, group = NULL, group2 = cluster, var1 = score1, var2 = score2) 
myFunc(data = mydf, group = group, group2 = cluster, var1 = score1, var2 = score2) 

两个调用提供以下错误分别是:

# Error 1 
Error: Aesthetics must be either length 1 or the same as the data (32): x, y, colour, label 

# Error 2 
Error in combine_vars(data, params$plot_env, cols, drop = params$drop) : 
At least one layer must contain all variables used for facetting 

预计d输出可以通过手动构建的曲线来获得:

means <- aggregate(cbind(score1, score2) ~ group + cluster, FUN = mean, data = mydf) 

# without facet 
ggplot(mydf, aes(x = score1, y = score2, color = cluster, label = cluster)) + 
    stat_ellipse(type = "norm", show.legend = FALSE, geom = "polygon", alpha = 0.1) + 
    geom_text(alpha = 0.5, show.legend = FALSE) + 
    geom_text(data = means, aes(x = score1, y = score2, color = cluster)) 

# with facet 
ggplot(mydf, aes(x = score1, y = score2, color = cluster, label = cluster)) + 
    stat_ellipse(type = "norm", show.legend = FALSE, geom = "polygon", alpha = 0.1) + 
    geom_text(alpha = 0.5, show.legend = FALSE) + 
    geom_text(data = means, aes(x = score1, y = score2, color = cluster)) + 
    facet_grid(. ~ group) 

回答

2

这里是基本stat_ellipse重复使用和不使用facet_grid。我会让你添加褶边。这里列名保留为字符串,因此使用aes_string而不是aes,并且使用as.formula将公式传递给函数。

myFunc <- function(df, var1, var2, group2, group1 = NULL) { 

    # Make this graph if no faceting needed 
    if (is.null(group1)) { 

    means_formula <- as.formula(paste(var1, "+", var2, "~", group2)) 
    means <- aggregate(means_formula, FUN = mean, data = df) 

    p <- ggplot(df, 
     aes_string(x = var1, y = var2, color = group2, label = group2)) + 
     stat_ellipse(type = "norm", show.legend = FALSE, 
      geom = "polygon", alpha = 0.1) 
    }else{ 

    means_formula <- as.formula(paste(var1,"+",var2,"~", group2,"+",group1)) 
    means <- aggregate(means_formula, FUN = mean, data = df) 

    p <- ggplot(df, 
     aes_string(x = var1, y = var2, color = group2, label = group2)) + 
     stat_ellipse(type = "norm", show.legend = FALSE, 
      geom = "polygon", alpha = 0.1) + 
     facet_grid(as.formula(paste(".~ ",group1))) 
    } 
    print(p) 
} 

myFunc(df = mydf, var1 = "score1", var2 = "score2", 
    group2 = "cluster", group1 = NULL) 

myFunc(df = mydf, var1 = "score1", var2 = "score2", 
    group2 = "cluster", group1 = "group") 

stat ellipse plot

2

首先,按功能,cluster范围分配group2到一个不存在的变量。替换:group2 = eval(arguments$cluster, data)group2 = eval(arguments$group2, data)

其次,您需要一个动态的facet_grid公式。目前您正在通过分组这不是数据集中的实际字段。但是,由于您在函数参数中没有引号,因此您需要检索函数参数group的字符串常量,这可以通过deparse(substitute(...))返回"group"来实现。

考虑附近其他功能的变量列表中添加的顶部:

grpname = deparse(substitute(group)) 

然后,用动态as.formula字符串连接或reformulate取代你facet_grid

facet_grid(as.formula(paste0(". ~ ", grpname))) 

facet_grid(reformulate(grpname)) 

当然,一切都可以如@ P-robot所示,使用带引号的函数参数动态运行。