在data.table中按组cbind列表的有效方法

时间:2015-08-30 11:23:23

标签: r data.table

我有一个data.frame

数据

data = structure(list(mystring = c("AASDAASADDLKJLKADDLKKLLKJLJADDLJLKJLADLKLADD", 
    "ASDSDFJSKADDKJSJKDFKSADDLKJFLAK"), class = c("cat", "dog")), .Names = c("mystring", 
    "class"), row.names = c(NA, -2L), class = "data.frame")

看起来像

#> dtt1
#                                      mystring class
#1 AASDAASADDLKJLKADDLKKLLKJLJADDLJLKJLADLKLADD   cat
#2              ASDSDFJSKADDKJSJKDFKSADDLKJFLAK   dog

我在mystring下的字符串的前20个字符中搜索“ADD”模式的开头和结尾位置,并将class视为组。

我正在使用str_locate stringr个包来执行此操作。这是我的尝试

setDT(dtt1)[, 
cbind(list(str_locate_all(substr(as.character(mystring), 1, 20),"ADD")[[1]][,1]),
      list(str_locate_all(substr(as.character(mystring), 1, 20),"ADD")[[1]][,2])), 
      by = class]

这会提供所需的输出

#   class V1 V2
#1:   cat  8 10
#2:   cat 16 18
#3:   dog 10 12

问题: 我想知道这是否是一种标准方法,或者这可以以更有效的方式完成。 str_locate在不同的列中提供匹配模式的startend位置,并将它们与cbind一起放在单独的列表中data.table ?另外,如何在此处为cbinded colnames指定columns

3 个答案:

答案 0 :(得分:4)

我认为你首先应该减少每组的操作,所以我首先要为所有组创建一个子字符串。

setDT(data)[, submystring := .Internal(substr(mystring, 1L, 20L))]

然后,使用stringi包(我不喜欢包装),你可以做(​​虽然目前不能保证效率)

library(stringi)
data[, data.table(matrix(unlist(stri_locate_all_fixed(submystring, "ADD")), ncol = 2)), by = class]
#    class V1 V2
# 1:   cat  8 10
# 2:   cat 16 18
# 3:   dog 10 12

或者,您可以避免每组matrixdata.table次呼叫,但在检测到所有位置后传播数据

res <- data[, unlist(stri_locate_all_fixed(submystring, "ADD")), by = class]
res[, `:=`(varnames = rep(c("V1", "V2"), each = .N/2), MatchCount = rep(1:(.N/2), .N/2)), by = class]
dcast(res, class + MatchCount ~ varnames, value.var = "V1")
#    class MatchCount V1 V2
# 1:   cat          1  8 10
# 2:   cat          2 16 18
# 3:   dog          1 10 12

第三个类似的选项可能是尝试首先在整个数据集上运行stri_locate_all_fixed,然后再向每个组unlist运行(而不是同时运行unliststri_locate_all_fixed每组)

res <- data[, .(stri_locate_all_fixed(submystring, "ADD"), class = class)]
res[, N := lengths(V1)/2L]
res2 <- res[, unlist(V1), by = "class,N"]
res2[, `:=`(varnames = rep(c("V1", "V2"), each = N[1L]), MatchCount = rep(1:(N[1L]), N[1L])), by = class]
dcast(res2, class + MatchCount ~ varnames, value.var = "V1")
#    class MatchCount V1 V2
# 1:   cat          1  8 10
# 2:   cat          2 16 18
# 3:   dog          1 10 12

答案 1 :(得分:3)

我们可以将matrix输出从str_locate_all更改为data.frame,并使用rbindlist创建列。

  setDT(data)[,rbindlist(lapply(str_locate_all(substr(mystring, 1, 20),
               'ADD'), as.data.frame)) , class]
  #   class start end
  #1:   cat     8  10
  #2:   cat    16  18
  #3:   dog    10  12

答案 2 :(得分:2)

这是我的表现。

sizeof(int*)/sizeof(int)