【发布时间】:2022-10-03 03:15:58
【问题描述】:
我正在努力以快速的方式从二进制文件中提取信息,而不使用特殊方法,而不能在稍后阶段在另一个上下文中回收代码。
我的实际用例包括来自 GWS 的二元降水雷达数据。如果您愿意,您可以从here 中选择任何解压文件。如果您获得了实际文件,这里是我到目前为止使用的代码。基本上,我正在使用readBin() |> rawToBits() |> matrix():
file <- \"raa01-ry_10000-2207250530-dwd---bin\"
con <- file(file, \"rb\")
# Read ascii header
meta <- readBin(con, what = raw(), n = 141, endian = \"little\") |> rawToChar()
# Read 2-byte data, dim = 900*900
data <- readBin(con, what = raw(), n = 900*900 * 2, endian = \"little\")
close(con)
# Set dimensions
dim(data) <- c(2, 900*900)
class(data)
#> [1] \"matrix\" \"array\"
typeof(data)
#> [1] \"raw\"
# Create a matrix with 16 columns
bits <- rawToBits(data) |> matrix(ncol = 16, byrow = TRUE)
class(bits)
#> [1] \"matrix\" \"array\"
typeof(bits)
#> [1] \"raw\"
dim(bits)
#> [1] 810000 16
否则,这里是head(bits) |> dput() 的输出:
bits <- structure(as.raw(c(0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01,
0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
0x01)), dim = c(6L, 16L))
数据仅存储在前 12 位中,后 4 位用于标记。但也有 1 字节产品,其中所有位都用于数据存储。所以我认为我需要一些灵活性。
packBits(\"integer\") 似乎只接受 32 位数据。但是,我能够使用as.raw(0) |> rep() |> append() |> packBits()-pipe 和apply() 在矩阵行上使用此函数将我的 12 位数据扩展到 32 位:
bits2int <- function(x) {
fill <- as.raw(0) |> rep(20)
append(x, fill) |> packBits(\"integer\")
}
result <- apply(bits[, 1:12], 1, bits2int)
head(result)
#> [1] 1027 1065 1065 1065 1065 1065
在线下,这种方法有效,但它需要大约。每个文件 12 秒,这太长了。考虑到 810,000 次迭代,一点也不奇怪。
想出一个可以应用于矩阵并逐列迭代执行一些as.numeric(x[,i])* 2^(i-1) 魔术并最终返回总和之类的函数可能会更有意义。所以这就是我现在卡住的地方。
但也许我只是错过了一些明显的东西,所以我对答案很好奇。
非常感谢您!
PS:您可以通过例如可视化结果matrix(result, ncol = 900) |> terra::rast() |> terra::plot() 如果您使用实际文件。
编辑1:
我想我会在这里提到 cmets 中给出的附加信息:
dwdradar 目前使用 Fortran 例程来导入 Radolan 数据。代码中列出了一个approach using R 以供进一步参考,但它似乎要慢得多。所以基本上,考虑到这个现有的代码,我想知道是否有办法让 R 方法 a) 更快 b) b2n(1)+b2n(2)+.... 部分更灵活地适用于 n 位数据。
编辑2:
处理完 cmets 中提供的附加材料后,我想我需要一个与 Fortran 的 IBITS() 等效的具有 position 和 length 参数的可用参数。但我认为这可能是一个更具体的后续问题。现在,我将继续筛选现有的方法。
-
在我的电脑上,初始化矩阵和按列操作从大约 10.5 秒减少到 8.5 秒
-
您是否尝试过
rdwd、dwdradar,或者这是一个不同的挑战?无论如何,我喜欢你在他们不在的情况下的工作流程。 -
感谢您的指点。实际上,这就是我要问的原因。
dwdradar使用 Fortran 例程进行导入。列出了一种使用 R 的方法,但它似乎要慢得多。所以基本上,考虑到这段代码,我想知道是否有办法让 R 方法更快,并且 `b2n(1)+b2n(2)+....` 部分更灵活以适用于 n-位数据。 -
注意到 github
brry关注速度,效率 lists other radolan,我们看到 KWB-R-ver3 我猜 ver3 的改进最大,其次是(?)to raster ver3,(对我来说还是有点模糊),但是 fortran 例程或 kwb 方法可以让您通过packBits填充步骤。如前所述,fortran 比 R 更快。n 位灵活性的用例是什么? -
既然你显然是杂食动物,让我推荐omd 供你考虑,