【问题标题】:Add function output to a data.table as new columns without naming them将函数输出添加到 data.table 作为新列而不命名它们
【发布时间】:2020-03-12 00:23:03
【问题描述】:

我有一个函数,它将现有 data.table 中的某些列作为输入,对它们执行计算,然后将结果输出为五个新列。

我想将五个新列附加到我现有的 data.table 中,但是如果不命名列就找不到合适的方法(这似乎是多余的,因为列已经在函数的输出中命名,并且它已经输出了一个data.table)。

注意:我的真实函数不是向量化的,所以我必须使用 'by' 参数。

此外,我的真实函数是另一个生成模型输出的函数的包装器,因此我已将该输出转换为带有as.data.table(pixiedust::dust(...)) 的表,这样我就不必多次运行它来获取模型输出的每个元素输出。

这是一个玩具示例:

# Load data.table:
library(data.table)

# Create data.table with example data:
mydt <- data.table(region = c("a", "b", "c"), 
                   count = c(0,50,200), 
                   pop = c(1000, 10000, 20000))

# Toy function:
rate <- function(count, pop, denom){

  dt = data.table(rawrate = count/pop, 
                  rateperpop = (count/pop)*denom)
  return(dt)

}

# Apply the function to mydt:
mydt[, rate(count = count, pop = pop, denom = 100000), by = 1:nrow(mydt)]

# which gives:
   nrow rawrate rateperpop
1:    1   0.000          0
2:    2   0.005        500
3:    3   0.010       1000

在上面的示例中,计算了新列,但它们没有添加到mydt,它保持不变。我试过链接:

mydt[][, rate(count = count, pop = pop, denom = 100000), by = 1:nrow(mydt)]

... 但这也不会添加列。

如果我尝试:

mydt[, .(rate(count = count, pop = pop, denom = 100000)), by = 1:nrow(mydt)]

由于by 子句,我得到一个错误,甚至删除它(我不能用我的真实函数做)只是输出新变量,它不会将它们添加到现有的 data.table 中。

我确信必须有一种语法简洁的方法来做到这一点,但无法弄清楚 - 任何解决方案都将不胜感激。

【问题讨论】:

  • 如果您需要添加新列,请执行:=。另外,不清楚为什么需要by
  • @Akrun 如果我使用:=,我不需要在左侧添加列名吗?这就是我要避免的...在这个玩具示例中不需要by,但它适用于我的真正功能,因为它不是矢量化的
  • @IceCreamToucan 你的意思是添加 mydt 作为函数的输入参数吗?

标签: r function data.table append multiple-columns


【解决方案1】:

一种选择是创建一个临时对象,然后在 LHS 上使用 :=names 的输出

new <- mydt[, rate(count = count, pop = pop, denom = 100000)]
mydt[, names(new) := new]

另一种选择是更改函数,以便它修改您的 data.table 本身

rate <- function(dt, count, pop, denom){
  dt[, `:=`(rawrate = count/pop, 
            rateperpop = (count/pop)*denom)]
}

mydt
#    region count   pop
# 1:      a     0  1000
# 2:      b    50 10000
# 3:      c   200 20000

rate(mydt, count = count, pop = pop, denom = 100000)

mydt
#    region count   pop rawrate rateperpop
# 1:      a     0  1000   0.000          0
# 2:      b    50 10000   0.005        500
# 3:      c   200 20000   0.010       1000

【讨论】:

  • 这是我通常会做的,但在这种情况下,我使用exactci::poisson.exact() 来获取我的费率的上下置信区间。该函数为每个参数接受一个或两个值,如果给出向量则返回错误。我可以像上面所做的那样从函数中分别提取每个元素并将其添加到 data.table 中,但这会增加不必要的计算时间,因为我将重复该函数以获取包装函数中的每个元素。
  • 另一方面,刚刚检查了单独调用元素的开销,也许这是要走的路,因为使用pixiedust::dust() 也会增加一些计算开销,避免额外的包依赖。您在 cmets 中的建议也适用于我,所以会接受这个答案。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-11-28
  • 1970-01-01
  • 1970-01-01
  • 2015-05-25
  • 1970-01-01
  • 2020-09-02
相关资源
最近更新 更多