应用返回多列数据表的函数时,保留原始数据表中的所有列

标签 r data.table

假设我有一个数据表。

# Load package
library(data.table)

# Dummy data table
dt <- data.table(foo = letters[1:10], 
                 bar = LETTERS[11:20], 
                 val = 100:109)

我想对此数据表的一列运行一个函数,该函数返回包含多个列的数据表。假设它看起来像这样:

# Function that returns data table
f <- function(x){
  data.table(stuff = paste0(x, "_stuff"),
             things = paste0("things_", x))
}

如果我在数据表中的 foo 上运行它,它会返回:

# Returns only columns from function 
dt[, f(foo)]
#>       stuff   things
#>  1: a_stuff things_a
#>  2: b_stuff things_b
#>  3: c_stuff things_c
#>  4: d_stuff things_d
#>  5: e_stuff things_e
#>  6: f_stuff things_f
#>  7: g_stuff things_g
#>  8: h_stuff things_h
#>  9: i_stuff things_i
#> 10: j_stuff things_j

太棒了!现在,我希望将返回的数据表附加到我的原始数据表中。如果我想将其附加到原始数据表中的几列,我可以像这样命名我想要保留的列:

# Returns named column and columns from function
dt[, .(foo, f(foo))]
#>     foo   stuff   things
#>  1:   a a_stuff things_a
#>  2:   b b_stuff things_b
#>  3:   c c_stuff things_c
#>  4:   d d_stuff things_d
#>  5:   e e_stuff things_e
#>  6:   f f_stuff things_f
#>  7:   g g_stuff things_g
#>  8:   h h_stuff things_h
#>  9:   i i_stuff things_i
#> 10:   j j_stuff things_j

但是,我想保留所有列,而不必单独命名它们。一种方法是使用 by:

# Retains all columns
dt[, f(foo), by = names(dt)]
#>     foo bar val   stuff   things
#>  1:   a   K 100 a_stuff things_a
#>  2:   b   L 101 b_stuff things_b
#>  3:   c   M 102 c_stuff things_c
#>  4:   d   N 103 d_stuff things_d
#>  5:   e   O 104 e_stuff things_e
#>  6:   f   P 105 f_stuff things_f
#>  7:   g   Q 106 g_stuff things_g
#>  8:   h   R 107 h_stuff things_h
#>  9:   i   S 108 i_stuff things_i
#> 10:   j   T 109 j_stuff things_j

reprex package于2020年2月18日创建(v0.3.0)

这为我提供了此测试用例所需的结果,但显然这仅在行是唯一的情况下才有意义。

我尝试使用类似 dt[, .(names(dt), f(foo))] 的内容,但这不能用作 names返回一个字符串向量,然后将其添加为一列。

显而易见的解决方案是使用 :=,如下所示:dt[, c("One", "Two") := f(foo)]。这给出了所需的结果但是我必须自己命名添加的列,而我想保留函数返回的列名称。

另一个解决方案可能是cbind(dt, dt[, foo(f)]),但这看起来很笨拙。

达到这个结果的正确方法是什么?

最佳答案

一些建议:

1)修改函数中的data.table:

f2 <- function(dt){
    cols <- c("stuff", "things")
    dt[, (cols) := lapply(paste0("_", cols), function(x) paste0(foo, x))]
}
f2(dt)

2)使用 NSE:

eval(substitute(dt[, (LHS) := RHS], list(RHS={a <- dt[, f(foo)]}, LHS=names(a))))

3)或者将结果分配给变量,然后通过引用进行更新,类似于Gainz在评论中提到的

a <- dt[, f(foo)]
dt[, names(a) := a]

我更喜欢选项 (3)。

关于应用返回多列数据表的函数时,保留原始数据表中的所有列,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/60287102/

相关文章:

r - 创建新的概率分布 R

r - 在 R 中选择 data.table 键

r - 使用 .SD 在 R data.table 中同时创建多个百分比变量的奇怪问题

r - 存在 2 个图例时如何更改图例点的大小

regex - 使用 R,检索文件名包含某些字符串的文件

r - 根据另一个向量的字符串匹配过滤 data.table

r - 使用 fread() 选择行和列,就像 read.csv.sql() 那样

r - 在 R 中的自定义函数中将参数传递给 data.table 的简单可重现示例

r - 避免 R 中的两个 for 循环

以 101% 的宽度和高度插入到 Word 中的 RMarkdown 图