arrays - 在 R data.table 中快速操作字符数组

标签 arrays r data.table

我有一个巨大的字符向量数据集(14GB,2 亿行)。我已经害怕了(在 48 核 128 GB 服务器上花了超过 30 分钟)。该字符串包含各个字段的串联信息。例如,我的表格的第一行如下所示:

2014120900000001091500bbbbcompany_name00032401

其中前 8 个字符代表 date YYYYMMDD 格式中,接下来的 8 个字符是 id ,接下来 6 time HHMMSS 格式,然后接下来的 16 个是 name (以 b 为前缀)最后 8 个是 price (小数点后两位)。

我需要将上面的1列data.table转换成5列:date, id, time, name, price .

对于上述字符向量,结果将是: date = "2014-12-09", id = 1, time = "09:15:00", name = "company_name", price = 324.01

我正在寻找一个(非常)快速且高效的 dplyr/data.table 解决方案。现在我正在使用 substr 来做到这一点:

date = as.Date(substr(d, 1, 8), "%Y%m%d");

而且执行起来要花很长时间!

Update: With readr::read_fwf I am able to read the file in 5-10 mins. Apparently, the reading is faster than fread. Below is the code:

f = "file_name";
num_cols = 5;
col_widths = c(8,8,6,16,8);
col_classes = "ciccn";
col_names = c("date", "id", "time", "name", "price");

# takes 5-10 mins
data = readr::read_fwf(file = f, col_positions = readr::fwf_widths(col_widths, col_names), col_types = col_classes, progress = T);

setDT(data);
# object.size(data) / 2^30; # 17.5 GB

最佳答案

可能的解决方案:

library(data.table)
library(stringi)

widths <- c(8,8,6,16,8)
sp <- c(1, cumsum(widths[-length(widths)]) + 1)
ep <- cumsum(widths)

DT[, lapply(seq_along(sp), function(i) stri_sub(V1, sp[i], ep[i]))]

给出:

         V1       V2     V3               V4       V5
1: 20141209 00000001 091500 bbbbcompany_name 00032401

包括一些额外的处理以获得所需的结果:

DT[, lapply(seq_along(sp), function(i) stri_sub(V1, sp[i], ep[i]))
   ][, .(date = as.Date(V1, "%Y%m%d"),
         id = as.integer(V2),
         time = as.ITime(V3, "%H%M%S"),
         name = sub("^(bbbb)","",V4),
         price = as.numeric(V5)/100)]

给出:

         date id     time         name  price
1: 2014-12-09  1 09:15:00 company_name 324.01
<小时/>

但你实际上正在读取一个固定宽度的文件。因此也可以考虑来自基本 R 的 read.fwf 或来自 read_fwf或者像我之前那样编写自己的 fread.fwf 函数:

fread.fwf <- function(file, widths, enc = "UTF-8") {
  sp <- c(1, cumsum(widths[-length(widths)]) + 1)
  ep <- cumsum(widths)
  fread(file = file, header = FALSE, sep = "\n", encoding = enc)[, lapply(seq_along(sp), function(i) stri_sub(V1, sp[i], ep[i]))]
}
<小时/>

使用的数据:

DT <- data.table(V1 = "2014120900000001091500bbbbcompany_name00032401")

关于arrays - 在 R data.table 中快速操作字符数组,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51265207/

相关文章:

C 数组 - 最大数及其位置

javascript - 表单提交并在得到响应的文本字段中设置值

android - 我这样写对吗? [小白]

r - 统计每列非零元素的个数——管道友好

r - 如何在远程 ssh 连接中在本地绘制 R 绘图?

r - 使用点-点时为 data.table 赋值

arrays - 查找最多具有 k 个奇数元素的不同连续子数组的数量

R: ggplot2 使两个 geom_tile 图具有相等的高度

r - 寻找一种更简洁的方法来根据多变量组内的值差异过滤 data.table

r - 使用 `{data.table}` : how to name a new column? 编程