String 为数据中的每一行构造标识符字符串

String 为数据中的每一行构造标识符字符串,string,r,data.table,String,R,Data.table,我有以下数据: library(data.table) d = data.table(a = c(1:3), b = c(2:4)) 并希望得到这个结果(以一种可以处理任意数量列的方式): 下面的内容很有用,但我希望能找到更简短、更清晰的内容 d = data.table(a = c(1:3), b = c(2:4)) d[, c := apply(mapply(paste, names(.SD), .SD, MoreArgs = list(sep = "_")),

我有以下数据:

library(data.table)
d = data.table(a = c(1:3), b = c(2:4))
并希望得到这个结果(以一种可以处理任意数量列的方式):

下面的内容很有用,但我希望能找到更简短、更清晰的内容

d = data.table(a = c(1:3), b = c(2:4))
d[, c := apply(mapply(paste, names(.SD), .SD, MoreArgs = list(sep = "_")),
               1, paste, collapse = "_")]

单向,仅稍微清洁:

d[, c :=  apply(d, 1, function(x) paste(names(d), x, sep="_", collapse="_")) ]

     a b       c
1: 1 2 a_1_b_2
2: 2 3 a_2_b_3
3: 3 4 a_3_b_4

要避免行循环,可以使用以下方法:

do.call(粘贴,c(lappy(名称(d),函数(n)粘贴0(n,”,d[[n]]),sep=“”)

基准:

N <- 1e4

d <- data.table(a=runif(N),b=runif(N),c=runif(N),d=runif(N),e=runif(N))

f1 <- function(d)
{
    do.call(paste, c(lapply(names(d), function(n)paste0(n,"_",d[[n]])), sep="_"))
}

f2 <- function(d)
{
    apply(d, 1, function(x) paste(names(d), x, sep="_", collapse="_"))
}

require(microbenchmark)

microbenchmark(f1(d), f2(d))

编辑说明:以前使用
N进行基准测试这里有一种方法使用
do.call('paste')
,但只需要一次调用
paste

我将在列为整数的情况下进行基准测试(因为这似乎是一个更合理的测试用例)

N <- 1e4

d <- setnames(as.data.table(replicate(5, sample(N), simplify = FALSE)), letters[seq_len(5)])

f5 <- function(d){
  l <- length(d)
  o <- c(1L, l + 1L) + rep_len(seq_len(l) -1L, 2L * l)
  do.call('paste',c((c(as.list(names(d)),d))[o],sep='_'))}


microbenchmark(f1(d), f2(d),f5(d))
Unit: milliseconds
  expr       min        lq    median        uq       max neval
 f1(d)  41.51040  43.88348  44.60718  45.29426  52.83682   100
 f2(d) 193.94656 207.20362 210.88062 216.31977 252.11668   100
 f5(d)  30.73359  31.80593  32.09787  32.64103  45.68245   100

N谢谢,用更少的apply肯定更清晰;目前的R-golf冠军:)我认为
apply
d
转换为矩阵。所以,会有副本,效率会降低。@Roland,你是对的,这绝对不是有效的。另一种方法是使用
by=names(d)
,但是你必须将值拉回到
paste
,或者你必须将
paste
拉到
j
hmm的外部,我加1,因为它看起来是正确的,但是经过测试,我认为你的
f1
没有正常工作,你只需要替换
d[,n]
使用
d[[n]]
在我的测试中,它实际上比Ricardo或agstudy的答案快2倍(运行与上面相同的代码,我也尝试了更大的n),我认为这个解决方案对于寻求速度的人来说是非常好的,在这个例子中,我正在寻找一个更短的表达式,而速度差异并不重要;再次感谢这个约束没有在问题中指定(正如我刚才意识到的),但是fwiw我实际上使用了这个版本,因为我需要在粘贴时保留列类型(我的实际计算比OP更复杂),并且
apply
会销毁该信息
Unit: milliseconds
  expr      min       lq   median       uq      max neval
 f1(d) 195.8832 213.5017 216.3817 225.4292 254.3549   100
 f2(d) 418.3302 442.0676 451.0714 467.5824 567.7051   100
N <- 1e4

d <- setnames(as.data.table(replicate(5, sample(N), simplify = FALSE)), letters[seq_len(5)])

f5 <- function(d){
  l <- length(d)
  o <- c(1L, l + 1L) + rep_len(seq_len(l) -1L, 2L * l)
  do.call('paste',c((c(as.list(names(d)),d))[o],sep='_'))}


microbenchmark(f1(d), f2(d),f5(d))
Unit: milliseconds
  expr       min        lq    median        uq       max neval
 f1(d)  41.51040  43.88348  44.60718  45.29426  52.83682   100
 f2(d) 193.94656 207.20362 210.88062 216.31977 252.11668   100
 f5(d)  30.73359  31.80593  32.09787  32.64103  45.68245   100