2017-02-11 21 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所示,使用帶引號的函數參數動態運行。