在美学中使用动态值不会刷新

The use of dynamic values in aesthetics doesn't refresh

在下面的代码中,我试图为数据框的每个特征显示它与其余特征的关系。

因此,使用 Peter Haschke 的多图方法,我已经能够显示所有组合。

suppressMessages(require(ggplot2))
suppressMessages(require(grid))

multiplot <- function(..., plotlist = NULL, file, cols = 1, layout = NULL) {
  plots <- c(list(...), plotlist)

  numPlots = length(plots)

  if (is.null(layout)) {
    layout <- matrix(seq(1, cols * ceiling(numPlots/cols)),
                    ncol = cols, nrow = ceiling(numPlots/cols))
  }

  if (numPlots == 1) {
    print(plots[[1]])

  } else {
    grid.newpage()
    pushViewport(viewport(layout = grid.layout(nrow(layout), ncol(layout))))

    for (i in 1:numPlots) {
      matchidx <- as.data.frame(which(layout == i, arr.ind = TRUE))
      print(plots[[i]], vp = viewport(layout.pos.row = matchidx$row,
                                      layout.pos.col = matchidx$col))
    }
  }
}


df <- data.frame(matrix(rnorm(400), nrow=100))
colnames(df) <- c("F1","F2","F3","F4")

pdf("example.pdf")
plots <- list()
count <- 1
for(i_feature in colnames(df)) {
  for(j_feature in colnames(df)) {
    if(i_feature == j_feature) {
      empty_df <- data.frame()
      blank_plot <- ggplot(empty_df) +
                    geom_point() +
                    xlim(0, 100) +
                    ylim(0, 100) +
                    theme(panel.grid.major = element_blank(),
                          panel.grid.minor = element_blank(),
                          axis.ticks=element_blank(),
                          axis.text.x=element_blank(),
                          axis.text.y=element_blank(),
                          axis.title.x=element_blank(),
                          axis.title.y=element_blank()
                    )
      blank_plot <- blank_plot + geom_text(aes(x=45,y=50,label=j_feature), size=6,fontface="bold")
      plots[[count]] <- blank_plot
    } else {
      plots[[count]] <- ggplot(df,aes_string(x=i_feature,y=j_feature)) +
                          geom_point(size = 1) +
                          theme(panel.grid.major = element_blank(),
                                panel.grid.minor = element_blank(),
                                axis.ticks=element_blank(),
                                axis.text.x=element_blank(),
                                axis.text.y=element_blank(),
                                axis.title.x=element_blank(),
                                axis.title.y=element_blank()
                          ) +
                          theme(legend.position="none")

    }
    count <- count + 1
  }
}

multiplot(plotlist = plots, cols = ncol(df))
garbage <- dev.off()

如您所见,我没有针对自身绘制一列,而是显示了一个带有列名称的标签。这个实现的问题是这一行:

blank_plot <- blank_plot + geom_text(aes(x=45,y=50,label=j_feature), size=6,fontface="bold")

没有正确刷新标签名称,因此要处理的最后一个特征是始终显示的特征,如屏幕截图所示。

谁能帮我解决这个问题?

ggplot2 在调用 plot 之前不会处理美学。因为这是在循环之后完成的,它发现 "F4" 作为 j_feature 的值。您可以通过

来测试
j_feature <- "test"
multiplot(plotlist = plots, cols = ncol(df))

解决方案相对简单:使用用于生成空白图的相关信息创建一个数据框,以便将标签存储在图对象中。

plots <- list()
count <- 1
for(i_feature in colnames(df)) {
  for(j_feature in colnames(df)) {

    if(i_feature == j_feature) {
      #create empty df with relevant parameters to feed to aes
      empty_df <- data.frame(x=45,y=50,label=j_feature)
      blank_plot <- ggplot(empty_df) +
        xlim(0, 100) +
        ylim(0, 100) +
        theme(panel.grid.major = element_blank(),
              panel.grid.minor = element_blank(),
              axis.ticks=element_blank(),
              axis.text.x=element_blank(),
              axis.text.y=element_blank(),
              axis.title.x=element_blank(),
              axis.title.y=element_blank()
        ) + geom_text(aes(x=x,y=y,label=label),fontface="bold")
      plots[[count]] <- blank_plot
    } else {
      plots[[count]] <- ggplot(df,aes_string(x=i_feature,y=j_feature)) +
        geom_point(size = 1) +
        theme(panel.grid.major = element_blank(),
              panel.grid.minor = element_blank(),
              axis.ticks=element_blank(),
              axis.text.x=element_blank(),
              axis.text.y=element_blank(),
              axis.title.x=element_blank(),
              axis.title.y=element_blank()
        ) +
        theme(legend.position="none")

    }
    count <- count + 1
  }
}
multiplot(plotlist = plots, cols = ncol(df))