1

我正在尝试根据给定变量的边界值拆分数据框,计算边界两侧的内容并输出矩阵(最好是数据框)。示例代码如下:

set.seed(1)
tdata <- data.frame(a1=rnorm(100, mean=5, sd=2), a2=rep(0:1, length.out=100))
tall <- sapply(1:9, function(x) {
  d <- split(tdata, tdata$a1 <= x)
  sapply(d, function (y) {
    1 - max(table(y$a2)/nrow(y))
  })
})

我的结果:

> allErr
           [,1]      [,2]      [,3]      [,4]      [,5]      [,6]      [,7]
FALSE 0.4949495 0.4895833 0.4943820 0.4933333 0.4444444 0.4411765 0.3333333
TRUE  0.0000000 0.2500000 0.4545455 0.4800000 0.4347826 0.4696970 0.4705882
      [,8] [,9]
FALSE  0.5  0.5
TRUE   0.5  0.5

我的连续变量是tdata$a1,我想每次使用 2 中的边界值拆分数据帧,对拆分的每个部分1:9执行计算a2,然后返回。

我的问题是:就优雅而言(查看plyr解决方案但无法避免使用第一个 sapply)以及更重要的是正确使用我可能不知道的其他 R 函数,最好的方法是什么。我还担心我的解决方案无法很好地扩展数据帧,而不是我目前拥有的数据帧(约 10000 行)。

4

2 回答 2

3

没有什么比这更优雅的了,但是这种修改可以通过拆分索引向量而不是整个数据框来帮助您的解决方案更好地扩展:

set.seed(1)
tdata <- data.frame(a1=rnorm(100, mean=5, sd=2), a2=rep(0:1, length.out=100))
tall <- sapply(1:9, function(x) {
         d <- split(seq_along(tdata$a2), tdata$a1 <= x)
         sapply(d, function (y) {
          1 - max(table(tdata$a2[y])/length(y))
         })
        })

这个玩具示例的性能提升相当小,很可能是因为您的数据框只有两列。如果您的真实数据框有更多列,您将看到拆分索引向量的更多好处。

于 2011-05-29T21:44:40.683 回答
1

也不确定优雅,但将内部函数分解为fun0a和'split-lapply'模式为tsplit,然后整个迭代是

fun0a <- function(x, ...)
    1 - max(table(x) / length(x))
tsplit <- function(thresh, x, splt, fun, ...)
    lapply(split(x, splt <= thresh), fun, ...)
sapply(1:9, tsplit, data$a2, tdata$a1, fun0a)

这使用内部lapply而不是sapply直接拆分单列数据,而不是通过索引或整个数据框。tsplit并且外部 sapply 可以在类似情况下重新使用,例如,当内部函数实际上依赖于数据帧时,传递索引(在外部 sapply 中计算一次)而不是值

fun0b <- function(i, df, ...)
    1 - max(table(df[i,"a2"]) / length(i))
with(tdata,
     sapply(1:9, tsplit, seq_along(a1), a1, fun0b, tdata))

tsplit是一个tapply所以可以实现为

tsplit <- function(thresh, x, splt, fun, ...)
    tapply(x, splt <= thresh, fun, ...)
于 2011-05-30T02:00:56.963 回答