【发布时间】:2021-04-02 10:03:52
【问题描述】:
使用:= 创建新列是我最喜欢的data.table 功能之一。我知道使用它一次添加多个列的两种方法。这是一个简单的例子
dt <- data.table("widths" = seq(2, 10, 2), "heights" = 8:4)
dt
widths heights
1: 2 8
2: 4 7
3: 6 6
4: 8 5
5: 10 4
假设我想添加两列,一列用于面积,另一列用于周长。第一种方法是调用,例如
new_cols <- c("areas", "perimeters")
my_fun <- function(x, y){
areas <- x * y
perimeters <- 2*(x + y)
return(list(areas = areas, perimeters = perimeters))
}
dt[ , (new_cols) := my_fun(widths, heights)]
dt
widths heights areas perimeters
1: 2 8 16 20
2: 4 7 28 22
3: 6 6 36 24
4: 8 5 40 26
5: 10 4 40 28
等价地,我们可以使用:=的函数形式如下:
dt[ , `:=`("areas" = widths * heights, "perimeters" = 2*(widths + heights))]
这两种方法都需要提前输入新列的名称。您可以手动输入它们,您可以在创建列之前将它们保存在一个对象中,或者您可以在:= 的左侧有一个生成名称的函数。我不知道的是一种在一次调用中同时获取名称和输出到:= 的方法。
有没有办法做到这一点?这是我希望做的一个例子:
dt[ , (new_cols) := NULL] # delete the previously added area and perimeter cols.
dt[ , `:=`(my_fun(widths, heights))]
dt
widths heights areas perimeters
1: 2 8 16 20
2: 4 7 28 22
3: 6 6 36 24
4: 8 5 40 26
5: 10 4 40 28
理想情况下,有一种方法可以让:= 看到my_fun() 返回名称,然后将这些名称用作新列的名称。我知道上面会产生一个错误,但我想知道是否有一种简单的方法可以获得所需的功能,因为这在有很多列或列名取决于函数输入的较大问题中很有用。
编辑:
我正在寻找的关键是通过引用分配这些列的方法,即使用:= 或 set(),我还想将输出的类保持为data.table。
【问题讨论】:
-
dt[ ,c(mget(names(.SD)),my_fun(widths, heights))],或者可能是cbind(dt, dt[, my_fun(widths, heights)]),但他们都没有就地做任何事情 -
谢谢。 mget() 选项很好,但我正在寻找的关键是使用
:=或 set() 进行就地更新。我已经编辑了这个问题以明确这一点。 -
我认为
dt[, do.call(":=", my_fun(widths, heights))]理论上会完全按照您的意愿行事,但目前无法正常工作。我已经提交了一个问题github.com/Rdatatable/data.table/issues/4950 -
感谢您提交问题。内置的东西真的很棒,因为这将允许在这种情况下使用
by和所有其他 data.table 工具。
标签: r data.table