在RStudio中的data.table()中使用plot()时,将使用错误组的值

时间:2014-12-16 13:29:13

标签: r data.table rstudio

我想生成一个分开的图表。在图表的上半部分是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

1 个答案:

答案 0 :(得分:7)

很好的捕获(已经+ 1&#39; d)!就我而言,示例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分配最大的组,并在内部为每个子组重用此内存,以避免重复的内存alloc / dealloc - 以提高效率。不确定(在黑暗中拍摄),但似乎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

将产生正确的情节。