根据列数将可变长字符串作为美感传递给ggplot2

时间:2018-06-26 03:59:23

标签: r ggplot2 aesthetics

我希望能够根据矩阵中的列数构建一个字符串,并将其作为美感传递给ggplotaes_string()函数似乎没有涵盖这一点。我想要这样做的原因是,我使用的是ggalluvial包,但是复杂性的重要性不如原理。我的代码如下:

library(ggplot2)
library(ggalluvial)
my_alluvial_plot <- function(scores, n_groups = 5) {

  score_names <- names(scores)
  scr_mat <- data.matrix(scores)
  n_cols <- ncol(scores)

  # create ntiles of scores so that flow can be seen between groups
  ranks <- apply(scr_mat, 2, function(x) {
    rk <- dplyr::ntile(x, n_groups)
    return(as.factor(rk))
  })

  to_plot <- data.frame(ranks)

  # build the string for the aes() function
  a_string <- ""
  for (i in 1:n_cols) {
    a_string <- paste0(a_string, "axis", i, " = to_plot[, ", i, "],")
  }
  # remove final comma
  a_string <- substr(a_string, 1, nchar(a_string) - 1)

  ggplot(to_plot,
         aes(eval(a_string))) +
    geom_alluvium(aes(fill = to_plot[, n_cols], width = 1/12)) +
    geom_stratum(width = 1/12, fill = "black", color = "grey") +
    scale_x_continuous(breaks = 1:n_cols, labels = score_names) +
    scale_fill_brewer(type = "qual", palette = "Set1")
}

df <- data.frame(col1 = runif(10),
                 col2 = runif(10),
                 col3 = rnorm(10),
                 col4 = rnorm(10))
my_alluvial_plot(df)

这将产生带有以下错误的空白图:

Warning: Ignoring unknown aesthetics: width
Error: Discrete value supplied to continuous scale

基本上,我想构建一个可以支持任意数量列的冲积图,因此评估后的ggplot代码最终会像

ggplot(to_plot,
       aes(axis1 = data[, 1], axis2 = data[, 2], axis3 = data[, 3], ...))

但是eval()parse()都不会产生任何有意义的东西。 aes_string()产生相同的问题。有什么办法可以系统地做到这一点?

1 个答案:

答案 0 :(得分:0)

无法在parse()之类的字符串上运行eval()"axis1 = col1, axis2 = col2"的原因是本身这样的字符串不是有效的R代码。但是整个ggplot通话吗?可以解析!

如果您像这样重做绘图,它将产生冲积绘图:

gg_string <- paste0("ggplot(to_plot,
                            aes(", a_string, ")) +
                       geom_alluvium(aes(fill = to_plot[, n_cols], width = 1/12)) +
                       geom_stratum(width = 1/12, fill = 'black', color = 'grey') +
                       scale_x_continuous(breaks = 1:n_cols, labels = score_names) +
                       scale_fill_brewer(type = 'qual', palette = 'Set1')")

eval(parse(text = gg_string))