【发布时间】:2020-02-18 18:12:17
【问题描述】:
假设我有一个数据表。
# 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 (v0.3.0) 于 2020 年 2 月 18 日创建
这给了我这个测试用例的期望结果,但显然这只有在行是唯一的情况下才有意义。
我尝试使用dt[, .(names(dt), f(foo))] 之类的东西,但这不起作用,因为names 返回一个字符串向量,然后将其添加为列。
显而易见的解决方案是像这样使用:=:dt[, c("One", "Two") := f(foo)]。这给出了所需的结果但我必须自己命名添加的列,而我想保留函数返回的列名。
另一个解决方案可能是cbind(dt, dt[, foo(f)]),但这似乎很笨拙。
实现这个结果的正确方法是什么?
【问题讨论】:
-
为什么不将
cbind(dt, dt[, f(foo)])包装在一个函数中? -
当然,我可以做到,但我想知道是否有规范的数据表方法可以做到这一点,因为这一定是一项相当常见的任务。
-
dt[, names(f(dt$foo)) := f(foo)][]之类的东西会起作用,但它并不是您真正想要的 -
@Gainz 是的,这需要
f被调用两次,这不是最优的。 -
如果您找到更好的解决方案,请@myname。
data.table是我用得最多的包之一,请多多学习!
标签: r data.table