【问题标题】:Best way to plot automatically all data.table columns using ggplot2使用 ggplot2 自动绘制所有 data.table 列的最佳方法
【发布时间】:2017-06-12 21:52:47
【问题描述】:

我正在尝试利用 data.tableggplot2 功能中的高级技巧来创建一个简单而强大的函数,该函数会自动将任意 data.table 的所有列 (y) 绘制(在一个图像中!)为输入列 (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

【问题讨论】:

  • 您的意思是将xyz 作为索引或字符串传递吗? plotAllXYbyZ(dt, x=1, y=3:10, z=2) 看起来像您想要传递列索引,但 aes(get(x)) 看起来像字符串,它期望 x = "mpg" 作为输入。选择一个并坚持下去。
  • 另外,正如diamonds 数据将说明的那样,当您有混合数据类型时,融合和分面是一个糟糕的解决方案 - 您最终会尝试在value 中混合分类和数字数据柱子。我不知道您希望diamonds 数据输出的外观如何。看看ggExtra::ggpairs,你可能可以破解那个函数来做你想做的事。
  • as.numeric(as.character()) 的转换在应用于 diamonds$clarity 时没有意义。在 y 轴上具有多个数字化因子和连续 x 轴的线图对我来说也没有用处。
  • 投票结束时“不清楚你在问什么”,因为这似乎没有经过深思熟虑。
  • 澄清:我们想要创建一个可以绘制所有这些的绘图函数:NUMERIC、FACTOR、CHARACTER。 IE。它会自动将任何 FACTOR、CHARACTER 列转换为 NUMERIC,以便可以绘制它们。 (所以用户不需要担心这些)。这就是我输入的原因:as.numeric(as.character())。此行将处理diamonds,其中diamonds$cut &lt;- as.character(diamonds$cut)。仅使用 as.numeric() 将导致 NA's

标签: r ggplot2 data.table


【解决方案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)

【讨论】:

  • 感谢您的努力。这不是我需要绘制的关系。请参阅下面的答案以查看需要去刻面的变量与需要融化的变量。请注意,我仍然没有找到混合“因素”和“数字”进行绘图的好方法。使用 ':=' 修改原始 data.table...
【解决方案2】:

感谢上面的 cmets,下面是实现所需输出的代码。 - 下图显示了为这些行生成的输出:

    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。更新:这个问题现在通过使用&lt;-copy(dt) 而不是&lt;-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))
}

[][]3

【讨论】:

  • 要复制数据表以便不修改原始数据表,请使用data.table::copyLots of details here.
  • 另外,除了if (T %in% ...),更常见、更易读的方式是if (any(...))
猜你喜欢
  • 1970-01-01
  • 2012-10-15
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-01-29
  • 1970-01-01
  • 2015-04-23
  • 1970-01-01
相关资源
最近更新 更多