【问题标题】:Working with rich objects in data.table columns使用 data.table 列中的丰富对象
【发布时间】:2014-05-23 08:00:32
【问题描述】:

假设我有一个 data.table,其中一列包含线性模型:

library(data.table)
set.seed(1014)

dt <- data.table(
  g = c(1, 1, 2, 2, 3, 3, 3),
  x = runif(7),
  y = runif(7)
)

models <- dt[, list(mod = list(lm(y ~ x, data = .SD))), by = g]

现在我想从每个模型中提取 r 平方值。我可不可以做 比这个好吗?

models[, list(rsq = summary(mod[[1]])$r.squared), by = g]

##    g      rsq
## 1: 1 1.000000
## 2: 2 1.000000
## 3: 3 0.004452

理想情况下,我希望能够消除 [[1]] 而不是依赖 知道前一个分组变量(我知道我希望每一行都是 它是自己的组)。

【问题讨论】:

  • 也许您应该解释一下您是否期望data.table 具有某些标准,或者您为什么需要这个?给定models并要求r.squared,除了按g分组,我只能想到使用lapply(...),然后将结果添加为新列。
  • 您可以按1:nrow(models) 分组以避免“了解”g
  • @arun 如果您知道您正在处理单个行,您可以在内部使用[[ 而不是[。这就是我对 dplyr 的想法(带有特殊的行分组器),我想知道数据表是否已经具有类似的功能。
  • 就因为我不知道更好,为什么使用[[1]]值得避免?
  • @DeanMacGregor 因为在这种情况下它是多余的

标签: r data.table


【解决方案1】:

这只是summary 是一个糟糕的小函数,它没有被矢量化。那么如何手动对其进行矢量化(这与@mnel的解决方案大致相同):

r.squared = Vectorize(function(x) summary(x)$r.squared)

models[, rsq := r.squared(mod)]
models
#   g  mod         rsq
#1: 1 <lm> 1.000000000
#2: 2 <lm> 1.000000000
#3: 3 <lm> 0.004451631

【讨论】:

  • 大多数使用线性模型的函​​数都不会被向量化,所以这种方法一般来说有点痛苦。
  • @hadley 是的,所以你必须自己应用函数 1 by 1 - 如何选择由你决定(显式 *applyVectorize 或你的原始解决方案),但是我看不出有办法绕过这个不幸的事实
【解决方案2】:

我的第一个想法是使用rapplyclasses='lm',但这不起作用。 sapply,但确实如此(令我惊讶)

library(data.table)
set.seed(1014)

dt <- data.table(
  g = c(1, 1, 2, 2, 3, 3, 3),
  x = runif(7),
  y = runif(7)
)

models <- dt[, list(mod = list(lm(y ~ x, data = .SD))), by = g]
models[, rsq := sapply(mod, function(x) summary(x)$r.squared)]

models
#     g  mod         rsq
#  1: 1 <lm> 1.000000000
#  2: 2 <lm> 1.000000000
#  3: 3 <lm> 0.004451631

由于.SD 作为环境的工作方式,对data.table 中的模型“做其他事情”可能会出现问题。

请参阅Why is using update on a lm inside a grouped data.table losing its model data? 了解可能发生的情况的示例。这是主题 错误#2590

【讨论】:

  • 在这里使用lapply 更有意义
  • @eddi - 除了lapply 将返回一个列表,从而转置响应。
  • 你说得对,我对data.table 输出两者的方式相同感到困惑
【解决方案3】:

这行得通吗?

library(data.table)
set.seed(1014)

dt <- data.table(
  g = c(1, 1, 2, 2, 3, 3, 3),
  x = runif(7),
  y = runif(7)
)
models <- dt[, list(rsq = summary(lm(y ~ x))$r.squared), by = g]
#   g         rsq
#1: 1 1.000000000
#2: 2 1.000000000
#3: 3 0.004451631

【讨论】:

  • 不,因为除了从模型中提取 r 平方外,我可能还想用它们做其他事情。
【解决方案4】:

我知道这个问题两年多没有出现,但解决方案已经存在,这里不再描述。

require(purrr)
require(broom)
map_df(models$mod, glance)

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-07-27
    • 1970-01-01
    • 2016-10-21
    • 1970-01-01
    • 1970-01-01
    • 2011-02-11
    相关资源
    最近更新 更多