【问题标题】:Appropriate use of `mapply()` to obtain matrix output适当使用`mapply()`获取矩阵输出
【发布时间】:2021-03-23 16:20:44
【问题描述】:

我想知道如何修改我的 mapply 调用以避免在我的最后一行代码之后得到:Error: $ operator is invalid for atomic vectors

注意:使用matrix(c(1, .1, 2, .2), nrow = 2) 只是为了简单。

我的预期输出是:

$Trus 
     [,1] [,2]
[1,]  1.0  2.0
[2,]  0.1  0.2

$Yu_Chen
     [,1] [,2]
[1,]  1.0  2.0
[2,]  0.1  0.2

我的可重现代码是:

ctlist <- function(mm, cont=FALSE, pos=1, outcom=1){
  
  mm <- mm[[1]]
  mm[mm$control==cont & mm$post == pos & mm$outcome == outcom, , drop = FALSE]
}

#=========
dinter <- function(m, pos, outcom){
  
  clist <- ctlist(mm=m, cont=TRUE, pos = pos, outcom = outcom)
  tlist <- ctlist(mm=m, cont=FALSE, pos = pos, outcom = outcom)
  
  matrix(c(1, .1, 2, .2), nrow = 2) # For simplicity
}
#=========
L1 = list(Trus = data.frame(control=c(T,F), post=c(1,1), outcome=c(1,1), time=c(2,2)),
          Yu_Chen = data.frame(control=c(F,F,T,T), post=c(1,2,1,2), outcome=c(1,1,1,1), time=c(1,2,1,2)) )

#=========

G <- function(m){
  
input <- rev(expand.grid(outcom = seq_len(max(m$outcom, na.rm = TRUE)), pos = seq_len(max(m$post, na.rm = TRUE))))
 
mapply(dinter, m=m, input$pos, input$outcom)
  
}
#=========

setNames(lapply(L1, G), names(L1))

#Error: $ operator is invalid for atomic vectors
#Called from: ctlist(mm = m, cont = TRUE, pos = pos, outcom = outcom)

【问题讨论】:

  • 创建mm &lt;- mm[[1]]后问题会出现在mm$control
  • 根据你定义函数的方式,即'dinter',我不确定为什么需要mapply/Map

标签: r function dataframe loops mapply


【解决方案1】:

函数ctlist有几个问题

mm <- mm[[1]]

通过提取第一列将“mm”更新为vector。现在,它没有任何暗淡属性。因此,如果我们执行下一行,它将不起作用,因为这些列不存在,因为它是 vector

mm[mm$control==cont & mm$post == pos & mm$outcome == outcom, , drop = FALSE]

现在,检查dinter,尚不清楚为什么 OP 创建了clisttlist,然后像预期的那样出乎意料地创建了matrix。它可以简化为

ctlist <- function(mm, cont=FALSE, pos=1, outcom=1){ 
  mm[mm$control==cont & mm$post == pos & mm$outcome == outcom, , drop = FALSE]
 }


lapply(L1, function(m) {

 input <- rev(expand.grid(outcom = seq_len(max(m$outcom,
      na.rm = TRUE)), pos = seq_len(max(m$post, na.rm = TRUE))))     
      dinter(m, pos = 1, outcom = 1)

 })
#$Trus
#     [,1] [,2]
#[1,]  1.0  2.0
#[2,]  0.1  0.2

#$Yu_Chen
#     [,1] [,2]
#[1,]  1.0  2.0
#[2,]  0.1  0.2

如果我们在 'input$pos'、'input$outcom' 的每个元素上应用 dinter,那么 m 应该是相同的。在 OP 的代码中,“m”也是mapply/Map 的输入。由于'm'是一个data.frame,单位是一列。因此,它在列上循环,而 input$pos 和 input$outcom 的循环是单个元素(在 'ctlist' 函数中创建一个问题,该函数期望 'mm' 作为 data.frame 以及长度为input$pos 和 'mm' 的列数不同)

lapply(L1, function(m) {

     input <- rev(expand.grid(outcom = seq_len(max(m$outcom, na.rm = TRUE)), pos = seq_len(max(m$post, na.rm = TRUE))))
     
     Map(dinter, MoreArgs = list(m = m), pos = input$pos, outcom = input$outcom)
    

})
#$Trus
#$Trus[[1]]
#     [,1] [,2]
#[1,]  1.0  2.0
#[2,]  0.1  0.2


#$Yu_Chen
#$Yu_Chen[[1]]
#     [,1] [,2]
#[1,]  1.0  2.0
#[2,]  0.1  0.2

#$Yu_Chen[[2]]
#     [,1] [,2]
#[1,]  1.0  2.0
#[2,]  0.1  0.2

如果我们想要展平列表,请使用cdo.call

do.call(c, lapply(L1, function(m) {

 input <- rev(expand.grid(outcom = seq_len(max(m$outcom, 
     na.rm = TRUE)), pos = seq_len(max(m$post, na.rm = TRUE))))
 Map(dinter, MoreArgs = list(m = m), pos = input$pos, 
         outcom = input$outcom)
   }))

【讨论】:

  • @rnorouzian 正如我之前提到的,您的dinter 正在返回一个矩阵作为输出。因此,如果您循环遍历“输入”列的每个值,我不确定我是否正确理解了逻辑。
  • @rnorouzian 有一些疑问。对于 input$pos 和 input$outcom 的每个值,您是否使用相同的 m。由于您简化了预期输出,因此很难知道您的确切预期
  • @rnorouzian 当我们不担心输出时,它会导致错误,因为Mapmapply 循环输入的每个对应元素。所以,mapply(dinter, m=m, input$pos, input$outcom) 意味着它循环遍历 'm' 的每一列、'pos' 的每个元素和 'outcom' 的每个元素
  • @rnorouzian 好的,每个循环中的m 是什么?它会保持不变吗?
  • @rnorouzian 对于“Yu_chen”,您会得到两个矩阵,因为有两行“输入”
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2017-08-01
  • 1970-01-01
  • 1970-01-01
  • 2018-05-03
  • 2015-07-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多