在data.table中拆分和合并字符串

时间:2019-06-26 11:41:13

标签: r data.table

假设我有以下数据:

kat  = c("a.b.c.d.e.f", "a.c.e.d.f.s", "a.v")

以R为基数的所需输出:

> splitted = strsplit(kat, "[.]")
> kat2 = sapply(splitted, function(x) paste(x[1:min(5, length(x))], collapse = "."))
> kat2
[1] "a.b.c.d.e" "a.c.e.d.f" "a.v" 

问题:如何使用data.table(以“可读”方式):

我知道该怎么做技术上正确的:

dat = data.table(kat = kat)
dat[, kat := sapply(strsplit(kat, "[.]"), 
                    function(x) paste(x[1:min(5, length(x))], collapse = "."))]

但是我发现它不是很可读,特别是如果我为更长的时间这样做。

我必须为每个操作创建一个函数吗?

kat3 = function(str){
  splitted = strsplit(str, "[.]")
  sapply(splitted, function(x) paste(x[1:min(5, length(x))], collapse = "."))
}

dat[, kat := kat3(kat)][]

或者是否有可能在data.table的索引编制中做到这一点?

dat[, kat := function(kat){
  splitted = strsplit(kat, "[.]")[[1]]
  paste(splitted[1:min(5, length(splitted))], collapse = ".")
  }, ]

2 个答案:

答案 0 :(得分:1)

您最后一次尝试失败,因为您需要将向量返回给kat。 sapplyVectorize可以帮上忙。

kat <- c("a.b.c.d.e.f", "a.c.e.d.f.s", "a.v")
library(data.table)
dat = data.table(kat = kat)

# error - function take a first element and return its transformation
dat[, kat2 := function(kat){
   splitted = strsplit(kat, "[.]")[[1]]
   paste(splitted[1:min(5, length(splitted))], collapse = ".")
}, ]
#> Error in `[.data.table`(dat, , `:=`(kat2, function(kat) {: RHS of assignment is not NULL, not an an atomic vector (see ?is.atomic) and not a list column.

smt <- function(kat){
   splitted = strsplit(kat, "[.]")[[1]]
   paste(splitted[1:min(5, length(splitted))], collapse = ".")
}

# to confirm
smt(kat)
#> [1] "a.b.c.d.e"

# use vectorize or sapply
smt_v <- Vectorize(smt)
smt_v(kat)
#> a.b.c.d.e.f a.c.e.d.f.s         a.v 
#> "a.b.c.d.e" "a.c.e.d.f"       "a.v"
sapply(kat, smt)
#> a.b.c.d.e.f a.c.e.d.f.s         a.v 
#> "a.b.c.d.e" "a.c.e.d.f"       "a.v"

如果要对许多变量执行操作,则可以遍历它们或使用lapply和.SDcols参数。如果编写function.R脚本并进行采购有很多转换,则可能是进行进一步研究的最佳方法。 :)

答案 1 :(得分:1)

使用正则表达式解决问题的另一种方法,我们提取单词直到出现第n个字符(这里是一个点)。这避免了字符串的拆分和连接步骤。

here和@Nathan Werth获得正则表达式帮助

library(data.table)
dat[, kat1 := stringr::str_extract(kat, "^(([^\\.]*\\.){0,4}[^\\.]*)")]

dat
#           kat      kat1
#1: a.b.c.d.e.f a.b.c.d.e
#2: a.c.e.d.f.s a.c.e.d.f
#3:         a.v       a.v