【问题标题】:Calculate multiple columns from one function and add them to data.frame从一个函数计算多列并将它们添加到 data.frame
【发布时间】:2014-12-29 20:07:14
【问题描述】:

我想从 data.frame 列上的函数返回多个结果,并将这些新列添加到同一个 data.frame 以及其他简单计算。

举个简单的例子,如果我想得到sin函数的积分值和绝对误差以及积分区间的中点:

df <- data.frame(Lower = c(1,2,3), Upper = c(2,3,4))
setDT(df)
getIntegral <- function(l, u) {
  n <- integrate(sin, mean(l), mean(u))
  list(Value=n$value, Error=n$abs.error)
}
df[,
   c('Value', 'Error', 'Mid') := {
     n <- getIntegral(Lower, Upper)
     list(n$Value,
          n$Error,
          (Lower+Upper)/2)
   }]
df
   Lower Upper     Value        Error Mid
1:     1     2 0.5738457 6.370967e-15 1.5
2:     2     3 0.5738457 6.370967e-15 2.5
3:     3     4 0.5738457 6.370967e-15 3.5

我不太喜欢我的方法,因为将新列的名称和分配给它们的值分开使我难以阅读,我怎样才能更好地完成这项任务?它是长数据处理链的一部分,所以我不想在外部创建临时变量,所以我更喜欢单独使用 data.tabledplyr 的解决方案。

【问题讨论】:

  • 你是说你不喜欢 data.table 语法??
  • 你的意思是这样的吗? setDT(df)[,":="(Value=getIntegral(Lower,Upper)$Value, Error=getIntegral(Lower,Upper)$Error, Mid =(Lower+Upper)/2)]
  • 或者这个?? setDT(df)[,c("Value","Rrror","Mid"):= with(getIntegral(Lower,Upper),list(Value,Error,(Lower+Upper)/2))]
  • @jlhoward,我想要setDT(df)[,":="(Value=getIntegral(Lower,Upper)$Value, Error=getIntegral(Lower,Upper)$Error, Mid =(Lower+Upper)/2)] 之类的东西,但我不想运行getIntegral 两次。
  • 那就用第一种方法吧。或者,您可以更改函数以返回包含所有三个值(Value、Error 和 Mid)的命名列表,然后只需使用 setDT(df)[,getIntegral(Lower,Upper),by=list(Lower,Upper)]

标签: r data.table dplyr


【解决方案1】:

RHS 应该是一个值列表,并且列表中的每个元素都被转换为一列(并在必要时回收)。

您的函数已经返回一个 list(每个长度为 1),(Lower+Upper)/2 返回一个包含 3 个值的向量(此处)。为了返回一个列表,你可以使用函数c(),如下:

df[, c('Value', 'Error', 'Mid') := c(getIntegral(Lower, Upper), list((Lower+Upper)/2))]
#    Lower Upper     Value        Error Mid
# 1:     1     2 0.5738457 6.370967e-15 1.5
# 2:     2     3 0.5738457 6.370967e-15 2.5
# 3:     3     4 0.5738457 6.370967e-15 3.5

这利用了c(list, list) 产生串联列表这一事实。

【讨论】:

  • 正如@jlhoward 在问题评论中所说,我是否可以拥有类似setDT(df)[,":="(Value=getIntegral(Lower,Upper)$Value, Error=getIntegral(Lower,Upper)$Error, Mid =(Lower+Upper)/2)] 的东西,而无需运行getIntegral 两次?我希望列的名称和分配给它们的值更接近,因为我有一个很长的计算列表。
  • 不,我认为这不可能。
猜你喜欢
  • 1970-01-01
  • 2016-10-17
  • 2015-10-25
  • 1970-01-01
  • 2021-09-30
  • 1970-01-01
  • 2015-05-24
  • 1970-01-01
  • 2013-04-14
相关资源
最近更新 更多