我想生成一个分开的图表。在图表的上半部分是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
答案 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
将产生正确的情节。