【问题标题】:Using apply() with a custom function and a second data frame将 apply() 与自定义函数和第二个数据框一起使用
【发布时间】:2017-07-07 22:34:33
【问题描述】:

我正在尝试从大量模型模拟中生成预测值,但我很难简单地做到这一点。我怀疑我需要 apply() 系列的东西,但我不知道语法。也许我对 apply() 的了解很薄弱。或者也许我的功能是错误的。有什么建议吗?

假设我从六个模型模拟中得到以下系数...

coef <- data.frame(intercept=c(2,3,5,7,2,1),
                   b1 = c(.2,.5,.6,.7,.9,.4),
                   b2 = c(10,11,12,11,9,10))

我想计算(预测值或)上面每一行和后面数据框每一行的线性组合...

df <- data.frame(age = c(50,20,19, 42),
                 height = c(60,72,79, 66))

...使用以下模型方程:

coef$intercept + coef$b1*df$age + coef$b2*df$height

做得对,我应该得到以下 24 个数据值:

612.0   726.0   795.8   670.4
688.0   805.0   881.5   750
755.0   881.0   964.4   822.2
702.0   813.0   889.3   762.4
587.0   668.0   730.1   633.8
621.0   729.0   798.6   677.8

为了得到以上内容,我尝试了以下函数和 apply() 的使用...

equation <-  function(...) coef$intercept + coef$b1*df$age + coef$b2*df$height
result <- apply(df, 1, equation)

...但我没有得到正确的答案。 “结果”数据框只是重复正确的对角线。我也收到了消息:

> Warning messages: 1: In coef$b1 * df$age :   longer object length is
> not a multiple of shorter object length

是的,我可以通过简单的矩阵乘法得到正确答案:

df$ones <- 1
df <- df[,c(3, 1, 2)]
result <- as.matrix(coef) %*% t(as.matrix(df))

但在我看来,应该能够更普遍地使用 apply() 和自定义函数来做到这一点。使用 apply() 更紧凑,并且降低了我的矩阵列顺序错误的风险。有什么建议吗?

【问题讨论】:

    标签: r apply


    【解决方案1】:

    如果你真的想使用apply,你可以这样做:

    result<- t(apply(coef, 1, function(x) x[1] + x[2]*df$age + x[3]*df$height))
    > result
         [,1] [,2]  [,3]  [,4]
    [1,]  612  726 795.8 670.4
    [2,]  688  805 881.5 750.0
    [3,]  755  881 964.4 822.2
    [4,]  702  813 889.3 762.4
    [5,]  587  668 730.1 633.8
    [6,]  621  729 798.6 677.8
    

    但是做矩阵乘法真的更好(而且更快)。

    【讨论】:

    • 感谢我应该坚持矩阵乘法的建议。关于上述答案的一件事是,我对通过数字索引引用“coef”列感到紧张。我想对我的列顺序错误的功能进行防呆。但你的回答激发了我写作的灵感:result&lt;- t(apply(coef, 1, function(x) x["intercept"] + x["b1"]*df$age + x["b2"]*df$height))
    【解决方案2】:

    我们可以通过%*% 做到这一点

    coef[,1] + as.matrix(coef[-1]) %*% t(df)
    #     [,1] [,2]  [,3]  [,4]
    #[1,]  612  726 795.8 670.4
    #[2,]  688  805 881.5 750.0
    #[3,]  755  881 964.4 822.2
    #[4,]  702  813 889.3 762.4
    #[5,]  587  668 730.1 633.8
    #[6,]  621  729 798.6 677.8
    

    【讨论】:

      【解决方案3】:

      这是我要做的:

      sapply(seq_along(1:nrow(coef)), function(x){
      
        sapply(seq_along(1:nrow(df)), function(y) {
          coef$intercept[[x]] + coef$b1[[x]]*df$age[[y]] + coef$b2[[x]]*df$height[[y]]
        })
      
      })
      

      结果:

           [,1]  [,2]  [,3]  [,4]  [,5]  [,6]
      [1,] 612.0 688.0 755.0 702.0 587.0 621.0
      [2,] 726.0 805.0 881.0 813.0 668.0 729.0
      [3,] 795.8 881.5 964.4 889.3 730.1 798.6
      [4,] 670.4 750.0 822.2 762.4 633.8 677.8
      

      使用两个 sapply。每个对象一个(dfcoef)。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2018-12-20
        • 1970-01-01
        • 2020-04-11
        • 1970-01-01
        • 1970-01-01
        • 2020-05-02
        • 2016-10-02
        • 2018-09-20
        相关资源
        最近更新 更多