【发布时间】:2019-07-30 22:12:35
【问题描述】:
我想从字符向量中获取原始字节向量(应用加密函数,该函数需要原始字节作为 data.table 列的所有值的输入)。
charToRaw不工作矢量化,但只处理矢量的第一个元素:
x <- c("hello", "my", "world")
charToRaw(x)
# Warning message:
# In charToRaw(x) : argument should be a character vector of length 1
# all but the first element will be ignored
charToRaw 是否有提供良好性能的矢量化版本?为什么base R的版本不提供矢量化版本?
我知道我可以使用 sapply 或 myapply 但我最终会在所有行上使用内部循环...
编辑 1: 结果应该是一个与“x”大小相同的向量,每个元素代表相应输入元素的原始字节。
编辑 2 + 3: 我的结果应该是这样的(例如,作为列表)
x.raw
[1] 68 65 6c 6c 6f
[2] 6d 79
[3] 77 6f 72 6c 64
问题在于 R 似乎不支持 raw 向量,因为 raw 本身就像字节向量...知道如何解决这个问题吗?
编辑 4 + 5:
我已经对当前的提案进行了基准测试:
library(microbenchmark)
x <- sample(c("hello", "my", "world"), 1E6, TRUE)
microbenchmark::microbenchmark(
sapply_loop = sapply(x, charToRaw),
lapply_loop = lapply(x, charToRaw),
vectorize_loop = { charToRawVec <-Vectorize(charToRaw, "x")
charToRawVec(x) },
split = split(charToRaw(paste(x, collapse = "")), rep(seq_len(length(x)), nchar(x))),
charToRaw_with_cpp = charToRaw_cpp(x),
times = 5
)
@Brian 答案中的 Rcpp 解决方案比所有其他建议快 4 到 5 倍(取决于字符串的长度):
Unit: milliseconds
expr min lq mean median uq max neval
sapply_loop 761.6041 1149.7972 1153.1992 1202.6303 1306.2110 1345.7531 5
lapply_loop 950.5337 972.1374 1172.4354 1134.9821 1300.4941 1504.0297 5
vectorize_loop 951.9297 983.2725 1134.0204 1147.1145 1250.9649 1336.8201 5
split 1201.5009 1275.7123 1409.3622 1425.0124 1529.5082 1615.0772 5
charToRaw_with_cpp 111.7791 113.1815 313.5623 384.7327 466.9929 491.1253 5
【问题讨论】:
-
一个使用
split的选项:split(charToRaw(paste(x, collapse = "")), rep(seq_len(length(x)), nchar(x)))虽然没有测试性能。 -
好主意!对一个字符使用多字节表示的编码可能会产生问题,但仍然是一种好方法!
-
事实上我无法提供我的输出的
dput,因为我不知道如何在向量中“嵌入”原始字节向量:-( -
是的,列表将是一个很好的结果类型。良好的性能是我的痛点(这就是为什么我要求
charToRaw的“矢量化”版本) -
@markus 我尝试了很多变体,但
split步骤总是对性能造成巨大拖累。我认为矢量化并加快速度的唯一方法是 Rcpp。
标签: r vectorization