【发布时间】:2021-12-17 03:05:00
【问题描述】:
问题:我有一个很大的 data.table dt,其中包含大约一百万个 x 和 y 值。这些 x-y 组合代表二维平面上的事件。我知道那架飞机的尺寸(iwidth、iheight)。
我想创建一个矩阵,除 data.table 中列出的 x-y 值外,其他任何地方都为 0。在这些位置,矩阵值应该为 1。通常,这很容易做到,但是要设置一百万个 x-y 值,常规方法不适合。
方法:由于不是每个 x-y 组合都会在 data.table 中表示,我首先创建一个具有正确维度的 0 矩阵。然后我将data.table指示的点处的0替换为1。
## initial setup (for easier testing we just use a data.frame, not a data.table)
iwidth = 4288
iheight = 8576
dt = data.frame( xval=sample(iwidth ,10), yval=sample(iheight ,10) )
## simple approach
mx = matrix(ncol=iwidth, nrow=iheight, data=0)
mx[dt$xval, dt$yval] = 1
## biganalytics approach
library(biganalytics)
mx = as.big.matrix(matrix(ncol=iwidth, nrow=iheight, data=0))
mx[dt$xval, dt$yval] = 1
失败:对于小数据,这工作得很好。但是,当您实际上有一个包含一百万行的 data.table 时,它需要很长时间。我认为biganalytics 包可能会有所帮助,但这仅适用于小数据,而对于大数据实际上更糟(请参阅下面的基准)。我也尝试过apply 或with,但对我来说它们也不起作用(我认为它们应该更慢)。
这些是上述方法的微基准测试结果(n=1)(dt5、dt50 等代表具有 5 行、50 行等的 data.table)。一旦我们到达较长的 data.tables(即矩阵中要替换的许多值),所花费的时间就会大大增加。
## Regular matrix:
Unit: milliseconds
expr min lq mean median uq max neval
dt5 130.8255 130.8255 130.8255 130.8255 130.8255 130.8255 1
dt50 87.2308 87.2308 87.2308 87.2308 87.2308 87.2308 1
dt500 86.7591 86.7591 86.7591 86.7591 86.7591 86.7591 1
dt5000 129.6120 129.6120 129.6120 129.6120 129.6120 129.6120 1
dt50000 4340.6080 4340.6080 4340.6080 4340.6080 4340.6080 4340.6080 1
## Biganalytics matrix:
Unit: milliseconds
expr min lq mean median uq max neval
dt5 0.988101 0.988101 0.988101 0.988101 0.988101 0.988101 1
dt50 0.779401 0.779401 0.779401 0.779401 0.779401 0.779401 1
dt500 9.814602 9.814602 9.814602 9.814602 9.814602 9.814602 1
dt5000 202.574901 202.574901 202.574901 202.574901 202.574901 202.574901 1
dt50000 19939.191600 19939.191600 19939.191600 19939.191600 19939.191600 19939.191600 1
【问题讨论】:
-
是稀疏矩阵的一种选择吗?例如
Matrix::sparseMatrix(i = dt$xval, j = dt$yval, x=1, dims=c(iwidth,iheight)) -
索引矩阵时,
dt$xval和dt$yval应该交换。yval是行索引,xval是列索引。 -
非常感谢@user20650! sparseMatrix 使之成为可能。我不得不写一点不同:
mx=Matrix::sparseMatrix(i = tra$xval+1, j = tra$yval+1, x=1, dims=c(iheight+1,iwidth+1))。 +1 对于 data.table 中的值是必需的,并且由于第二条评论中提到的内容,iheight 和 iwidth 的切换是必要的(非常感谢@RuiBarradas)。之后,我使用mx=as.matrix(mx[-1,-1])将其转换为常规矩阵(-1 用于删除之前添加的行和列) -
几个挑剔的东西:你指的是
data.table,但你创建了一个data.frame。data.table的优势之一是处理大型数据集的速度,因此了解这是否真的是您正在使用的内容会很有帮助。此外,也许您的示例与您实际使用的示例相比有所简化,但我不知道百万行数据框或百万项数字矩阵本身会构成“大数据”。大到足以考虑性能,当然,但大到需要计算机之外的特殊工具?不一定。 -
@camille,感谢您的评论,是的,我在示例中使用了 data.frame,但在现实世界中,我使用了 data.table,但仍然存在相同的问题(另请参阅第一条评论在我的第一个代码块中;)至于“大数据”的定义,很好,当然可以拥有比这更多的数据,但是对于我使用的 PC,即使是 500,000 行也需要花费大量时间来完成这项任务,而且我将不得不编写这个脚本供其他人使用,我不知道他们有什么 PC 能力。所以数据量很大,我得注意我采用的方法。