使用ggplot2自动绘制所有data.table列的最佳方法

时间:2017-06-12 21:52:47

标签: r ggplot2 data.table

我试图利用data.tableggplot2功能的高级技巧创建一个简单而强大的功能,自动绘制(在一个图像中!)所有列(y)任意data.table作为输入列(x)的函数,由列(k)进行优化调整 - 这样我们就可以使用单行快速可视化所有数据列:

dt <- data.table(diamonds[1:100,])[order(carat),cut:=as.character(cut)] 

plotAllXYbyZ(dt)
plotAllXYbyZ(dt, x="carat", k="color")
plotAllXYbyZ(dt, x=1, y=c(2,8:10), k=3)

澄清:挑战在于列可以是任何一种类型(数字,字符或因子)。我们想要一个自动处理这个功能的功能。 - 即它应该能够使用melt和ggplot绘制所有请求的列,正如我在下面的答案中尝试的那样。

更新:我的代码发布在答案中。它的功能(即显示所需的图)。但它有一个问题,即:它修改原始data.table。 - 为了解决这个问题,我在这里提出了一个新问题:Don't want original data.table to be modified when passed to a function

2 个答案:

答案 0 :(得分:1)

我希望这适合你:

plotAllXYbyZ <- function(dt, x, y, z) {
  # to make sure all columns to be melted for ploting are numerical 
  dt[, (y):= lapply(.SD, function(x) {as.numeric(as.character(x))}), .SDcols = y]
  dts <- melt(dt, id = c(x,z), measure = y)
  ggplot(dts, aes_string(x = colnames(dt)[x], y = "value", colours = colnames(dt)[z])) +
    geom_line() + facet_wrap(~ variable)
}

dt <- data.table(mtcars)    

plotAllXYbyZ(dt, x=1, y=3:10, z=2)

enter image description here

答案 1 :(得分:0)

感谢上面的评论,下面是实现所需输出的代码。 - 下图显示了这些生产线的产出:

    dtDiamonds <- data.table(diamonds[1:100,])[order(carat),cut:=as.character(cut)]
    plotAllXYbyZ(dtDiamonds);   
    plotAllXYbyZ(dtDiamonds, x="carat", k="color") 
    plotAllXYbyZ(dtDiamonds, x=1, y=c(2,8:10), k=3)

为了做到这一点,我必须引入一个函数将所有内容转换为数字。 唯一剩下的问题是原始dtDiamonds被修改了! - 因为':='。要解决此问题,我在此处发布了一个单独的问题:为了解决此问题,我在此处提出了一个新问题:Don't want original data.table to be modified when passed to a function。更新:现在使用<-copy(dt)代替<-dt来解决此问题。

# A function to convert factors and characters to numeric. 
my.as.numeric <- function (x) {
  if (is.factor(x)) {
    if (T %in% is.na(as.numeric(as.character(x)))) # for factors like "red", "blue"
      return (as.numeric(x))   
    else                                           # for factors like  "20", "30", ...
      return (as.numeric(as.character(x)))         # return: 20, 30, ...
  }
  else if (is.character(x)) {
    if (T %in% is.na(as.numeric(x))) 
      return (as.numeric(as.ordered(x)))  
    else                            # the same: for character variables like "20", "30", ...
      return (as.numeric(x))        # return: 20, 30, ... Otherwise, convert them to factor
    return (x)   
  }
}

 plotAllXYbyZ <- function(.dt, x=NULL, y=NULL, k=NULL) { 
  dt <- copy(.dt)    # NB: If copy is not used, the original data.table will get modified !
  if (is.numeric(x)) x <-  names(dt)[x]
  if (is.numeric(y)) y <-  names(dt)[y]
  if (is.numeric(k)) k <-  names(dt)[k]

  if (is.null(x)) x <- names(dt)[1]    

  "%wo%" <- function(x, y) x[!x %in% y]    
  if (is.null(y)) y <- names(dt) %wo% c(x,k)

  # to make sure all columns to be melted for plotting are numerical 
  dt[, (y):= lapply(.SD, function(x) {my.as.numeric(x)}), .SDcols = y]

  ggplot(melt(dt, id=c(x,k), measure = y)) + 
    geom_step(aes(get(x),value,col=variable))  +
    ifelse (is.null(k), list(NULL), list(facet_wrap(~get(k))) ) + 
    labs(x=x, title=sprintf("variable = F (%s | %s)", x, k))
}

enter image description here [enter image description here] [enter image description here] 3