给定data.table具有任意数量的列
dt = data.table( a = letters[1:5], b = rep('-', 5), c = LETTERS[1:5] )
# a b c
# 1: a - A
# 2: b - B
# 3: c - C
# 4: d - D
# 5: e - E
Run Code Online (Sandbox Code Playgroud)
以及任意format字符串,该字符串具有与列数相对应的多个占位符
format = '%s0%s1%s'
Run Code Online (Sandbox Code Playgroud)
如何在sprintf不使用所有列名显式调用的情况下应用?只提供data.table不会起作用的,因为sprintf在这种情况下需要3个参数。打电话sprintf(format, dt$a, dt$b, dt$b)是没有选择的,因为我既不知道format也不是data.table事先知道。同样sapply,行索引将不起作用,因为必须对保留其顺序的行子集执行操作。
idx = seq( 1, by = 2, to = 5 )
Run Code Online (Sandbox Code Playgroud)
因此,目标是通过发出假设命令
dt[ idx, sprintf( format, * )]
Run Code Online (Sandbox Code Playgroud)
实现这个
# [1] "a0-1A" "c0-1C" "e0-1E"
Run Code Online (Sandbox Code Playgroud)
可以通过调用
cols = paste( names( dt ) ), collapse=',' )
# "a,b,c"
eval( parse( text = sprintf( 'dt[ idx, sprintf( format,%s )]', cols ) ) )
# [1] "a0-1A" "c0-1C" "e0-1E"
Run Code Online (Sandbox Code Playgroud)
但是,这相当神秘,而且绝对不是干净的代码,如果data.table程序包本身有更多语义的方式,那就更好了。因此,问题基本上是是否存在一个。到目前为止,谷歌和data.table手册都没有给我答案。此外,我既不想使用paste某些/多个列,又不想使用所有列,也不想通过使用来实现此目的data.frame。我正在寻找流畅的data.table语法。
我们可以通过将做到这一点sprintf的论点do.call
dt[, do.call(sprintf, c(.SD, fmt = format))]
#[1] "a-A" "b-B" "c-C" "d-D" "e-E"
Run Code Online (Sandbox Code Playgroud)
如果需要在“ dt”中将其创建为列,请为其分配(:=)以创建新列
dt[, newCol := do.call(sprintf, c(.SD, fmt = format))]
Run Code Online (Sandbox Code Playgroud)
我们也可以使用pastewithdo.call
dt[, newCol := do.call(paste0, .SD)]
Run Code Online (Sandbox Code Playgroud)