【发布时间】:2016-11-12 19:44:23
【问题描述】:
我设计了一种解决方案,可以从两个单独的数据表的多个列中查找值,并添加一个基于新列的值计算(多个条件比较)。代码如下。它涉及在计算两个表的值时使用 data.table 和连接,但是,这些表没有连接到我正在比较的列上,因此我怀疑我可能没有获得 data.tables 固有的速度优势我已经阅读了很多,并且很高兴能够进入。换句话说,我加入了一个“虚拟”专栏,所以我认为我加入的不是“正确”。
这个练习是,给定一个 X 乘 X 网格 dtGrid 和一个 X^2 随机事件列表 dtEvents ,以确定在每个网格点的 1 单位半径内发生了多少事件。代码如下。我选择了一个 100 X 100 的网格大小,在我的机器上运行连接需要大约 1.5 秒。但是如果不引入巨大的性能影响(200 X 200 需要约 22 秒),我就不能做得更大。
我真的很喜欢能够在val 语句中添加多个条件的灵活性(例如,如果我想添加一堆 AND 和 OR 组合,我可以这样做),所以我想保留它功能。
有没有办法“正确”使用 data.table 连接(或任何其他 data.table 解决方案)来获得更快/更有效的结果?
非常感谢!
#Initialization stuff
library(data.table)
set.seed(77L)
#Set grid size constant
#Increasing this number to a value much larger than 100 will result in significantly longer run times
cstGridSize = 100L
#Create Grid
vecXYSquare <- seq(0, cstGridSize, 1)
dtGrid <- data.table(expand.grid(vecXYSquare, vecXYSquare))
setnames(dtGrid, 'Var1', 'x')
setnames(dtGrid, 'Var2', 'y')
dtGrid[, DummyJoin:='A']
setkey(dtGrid, DummyJoin)
#Create Events
xrand <- runif(cstGridSize^2, 0, cstGridSize + 1)
yrand <- runif(cstGridSize^2, 0, cstGridSize + 1)
dtEvents <- data.table(x=xrand, y=yrand)
dtEvents[, DummyJoin:='A']
dtEvents[, Counter:=1L]
setkey(dtEvents, DummyJoin)
#Return # of events within 1 unit radius of each grid point
system.time(
dtEventsWithinRadius <- dtEvents[dtGrid, {
val = Counter[(x - i.x)^2 + (y - i.y)^2 < 1^2]; #basic circle fomula: x^2 + y^2 = radius^2
list(col_i.x=i.x, col_i.y=i.y, EventsWithinRadius=sum(val))
}, by=.EACHI]
)
【问题讨论】:
-
弗兰克:被指控有罪。你是绝对正确的。它应该说 X+1 x X+1 网格...我希望所有事件点都适合网格,所以我必须包括 0 X 和 Y 网格点。也就是说,我试图解决的问题受此更改的影响最小......事件的数量和网格大小有些随意,除了它们都相当大。谢谢指正。
-
对于它的价值,如果您能够在每个维度上独立地将标准从单位圆切换到 +/-1,它可以更快:
system.time(dtEvents[, { L = lapply(.SD, function(x) rep(as.integer(floor(x)), each=4L)); .( x = L[[1]] + 0:1, y = L[[2]] + rep(0:1, each=2L) ) }, .SDcols = x:y][, .N, by=x:y])。这就是我最初认为你在做的事情。
标签: r join data.table