【问题标题】:Values of the wrong group are used when using plot() within a data.table() in RStudio在 RStudio 的 data.table() 中使用 plot() 时使用了错误组的值
【发布时间】:2014-12-16 13:29:13
【问题描述】:

我想生成一个划分图。图的上半部分是a 组的值,下半部分是b 组的值。我正在使用data.table() 来执行此操作。这是我用来生成示例并设置图形输出的代码:

library(data.table)
set.seed(23)
Example <- data.table('group' = rep(c('a', 'b'), each = 5), 'value' = runif(10))
layout(1:2)
par('mai' = rep(.5, 4))

在通常的 r 控制台中运行以下行时,将使用正确的值进行绘图。在 Rstudio 中运行相同的代码时,第二组的值用于两个图表:

Example[, plot(value, ylim = c(0, 1)), by = group] # Example 1
Example[, .SD[plot(value, ylim = c(0, 1))], by = group] # Example 2

在示例 2 的子集 data.table .SD[] 中添加逗号时,Rstudio 中也会生成正确的输出:

Example[, .SD[, plot(value, ylim = c(0, 1))], by = group] # Example 3

当使用barplot() 而不是plot() 时,Rstudio 也会使用正确的值:

Example[, barplot(value, ylim = c(0, 1)), by = group] # Example 4

我是否忽略了什么或者这是一个错误?

系统:Windows 7,Rstudio Desktop v0.98.1091,R 3.1.2,data.table 1.9.4

【问题讨论】:

  • 所有绘图均在我的设置中正确生成:Rstudio 0.98.1028, R 3.0.2。

标签: r data.table rstudio


【解决方案1】:

不错的收获(已经 +1 了)!就我而言,示例 3 也没有产生正确的绘图(OS X 10.10.1、R 3.1.2、Rstudio 0.98.1091)。

这里的 R 控制台/GUI 和 Rstudio 之间的唯一区别是绘图设备。 RStudio 似乎使用的是原生图形设备 RstudioGD,而 R 控制台/GUI 使用的是 Quartz

通过调试graphics:::plot.default,我能够将问题缩小到函数plot.xy()。该函数调用不同的图形设备(如上图)。

例如,通过调用函数quartz() 来启动Quartz,然后运行您的代码就可以了!

FWIW 这个问题也可以使用dplyr() 重现:

require(dplyr)
df = as.data.frame(Example)
my_fun = function(x) {plot(x, ylim=c(0,1)); 1L }
df %>% group_by(group) %>% summarise(my_fun(value))

会导致同样的错误情节。

这很可能是由于子组在 data.table 中的处理方式(我认为dplyr 应该以与 data.table 相同的方式处理),您可以通过以下方式查看:

Example[, print(sapply(.SD, address)), by=group]
#         value 
# "0x105bbf5b8" 
#         value 
# "0x105bbf5b8" 
# Empty data.table (0 rows) of 1 col: group

data.table.SD 分配最大的组,并在内部为每个子组重用此内存,以避免重复的内存分配/释放 - 以提高效率。不确定(这里在黑暗中拍摄),但似乎RstudioGD 没有放开与子组链接的指针,并且随着子组中的数据更新,情节也更新了。您可以通过以下方式验证这一点:

# on RstudioGD
debug(graphics:::plot.default)
set.seed(23)
Example <- data.table('group' = rep(c('a', 'b'), each = 5), 'value' = runif(10))
layout(1:2)
par('mai' = rep(.5, 4))
Example[, plot(value, ylim = c(0, 1)), by = group] # Example 1
undebug(graphics:::plot.default)

继续按回车键,您会看到第一个情节被正确绘制了。当添加第二个情节时,第一个情节也发生了变化。这可能是最近 Rv3.1+ 更改的结果,它浅层复制函数参数而不是深层复制(同样,这里是在黑暗中拍摄)。

您可以通过显式复制 value 来临时解决此问题:

Example[, plot(copy(value), ylim = c(0, 1)), by = group] # Example 1

将产生正确的情节。

【讨论】:

  • 非常感谢您的广泛回答和使用 copy() 的提示。这看起来是目前最简单的解决方法。
  • 如果这可能有帮助@Arun,如果我从控制台运行示例 1 或 2,我会得到 Jonas 所说的正确图,但是如果我随后打印图或复制为元文件和然后粘贴(例如到 Word)我得到有缺陷的情节。复制为位图不这样做。最后,试试没有 ylim=c(0,1) 的例子。当我打印或复制时,我得到了每个图的适当 y 范围,但重复的最后一个数据 - 在第一个图中部分偏离了比例。
  • Windows 7,R 3.1.2,data.table 1.9.4
猜你喜欢
  • 1970-01-01
  • 2019-12-29
  • 1970-01-01
  • 1970-01-01
  • 2014-09-16
  • 1970-01-01
  • 1970-01-01
  • 2023-02-05
  • 1970-01-01
相关资源
最近更新 更多