1

我想sapply用 for 循环替换的行为。(如果有兴趣,请参阅下面的原因。)

这是我的代码的 sapply 版本的简化:

slow_function=function(n) c(n*n, 0, (-n)^n, -1, +1)
quick_analysis=function(res) res[1]+res[3]

results=sapply(1:8,function(n){
  res=slow_function(n)
  a=quick_analysis(res)
  b=table(sign(res))
  list(
    a=a,
    up=b['1'],
    down=b['-1'],
    level=b['0']
    )
  })

这给了我:

      [,1] [,2] [,3] [,4] [,5]  [,6]  [,7]    [,8]    
a     0    8    -18  272  -3100 46692 -823494 16777280
up    2    3    2    3    2     3     2       3       
down  2    1    2    1    2     1     2       1       
level 1    1    1    1    1     1     1       1  

(这很好,尽管顺便说一句,我实际上希望它转置,将 n 的值作为行,将 a, up, down, level 作为列。但是,没问题,我知道该怎么做。)

当我把它变成一个for循环时:

results=vector()
for(n in 1:8){
  res=slow_function(n)
  a=quick_analysis(res)
  b=table(sign(res))
  results[n]=list(
    a=a,
    up=b['1'],
    down=b['-1'],
    level=b['0']
    )
  }

然后我收到 8 条警告消息,例如:

1: In results[n] = list(a = a, up = b["1"], down = b["-1"], level = b["0"]) :
  number of items to replace is not a multiple of replacement length

结果非常不同:

[[1]]
[1] 0

[[2]]
[1] 8

[[3]]
[1] -18

[[4]]
[1] 272

[[5]]
[1] -3100

[[6]]
[1] 46692

[[7]]
[1] -823494

[[8]]
[1] 16777280

我有点明白发生了什么。我不知道的是获得我想要的结果的魔法咒语!我已经尝试将结果初始化为matrix()list()相反,具有相同的输出。

旁白:为什么我要使用 for 循环?我实际上想在 sapply 循环的每次传递中进行两次计算。换句话说,只进行 8 次调用,slow_function但返回 16 行结果。如果 sapply 允许它,我的代码将类似于:

results=sapply(1:8,function(n){
  res=slow_function(n)
  a=quick_analysis(res)
  b=table(sign(res))
  list(
    a=a,
    up=b['1'],
    down=b['-1'],
    level=b['0']
    )
  res=-res  #Modify res
  a=quick_analysis(res)
  b=table(sign(res))
  list(
    a=a,
    up=b['1'],
    down=b['-1'],
    level=b['0']
    )
  })

所需的输出:(对不起,格式关闭,我必须手工制作)

      [,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8] [,9] [,10] [,11] [,12]  [,13]   [,14] [,15]   [,16]   
a     0     0    8     -8   -18  18    272  -272 -3100 3100  46692  -46692 -823494 823494 16777280 -16777280
up    2     2    3     1    2    2     3     1    2     2     3      1      2       2      3        1
down  2     2    1     3    2    2     1     3    2     2     1      3      2       2      1        3
level 1     1    1     1    1    1     1     1    1     1     1      1      1       1      1        1  
4

2 回答 2

2

对于如何在没有数据的情况下完成此任务并知道您的目标是什么,这是在黑暗中拍摄的:

slow_function=function(n) c(n*n, 0, (-n)^n, -1, +1)
quick_analysis=function(res) res[1]+res[3]

results=lapply(1:8,function(i){
  res=slow_function(i)
  FUN <- function(res.in) {
      a=quick_analysis(res.in)
      b=table(sign(res.in))
      data.frame(
       a=a,
       up=b['1'],
       down=b['-1'],
       level=b['0']
       )
  }
  data.frame(id=c("p", "n"), it=i, rbind(FUN(res), FUN(-res)))
})

DAT <- do.call(rbind, results)
with(DAT, DAT[order(id, it), ]) #maybe the order you're after

编辑:

这会给你你想要的东西(索引和 id 从来没有必要我这样做是因为我不知道你想要的输出;你可以删除你认为合适的主题):

rownames(DAT) <- NULL
t(DAT[, -c(1:2)])
于 2012-07-23T03:21:36.717 回答
1

当它们都具有相同的长度时,sapply 默认会简化结果。因此,您需要手动组合 for 循环返回的各种子列表,

results2 = list()
for (n in 1:8){
  res=slow_function(n)
  a=quick_analysis(res)
  b=table(sign(res))
  results2[[n]] = list(
    a=a,
    up=b['1'],
    down=b['-1'],
    level=b['0']
  )

}

do.call(cbind, results2)
于 2012-07-23T09:27:16.497 回答