【问题标题】:Avoid simplification in apply()避免在 apply() 中简化
【发布时间】:2018-11-26 13:09:05
【问题描述】:

很简单的问题。

有没有办法避免apply()中的简化?

我需要这样做,因为我有一个 apply,它有时可以简化(它确实做到了)有时不能,因此根据输入创建不同的数据结构,所以我想完全避免它。

我需要类似于mapply() 中的SIMPLIFY = FALSE 的东西,或者像vapply() 中那样控制输出的机制。


简单的可重现示例:

mimat <- matrix(c(1,2,3,4,5,6), nrow = 2)
mimat2 <- matrix(c(3,2,3,4,5,6), nrow = 2)

apply(mimat, MARGIN = 2, function(x) { 
                              if (is.element(el = 1, x)) return(c(0,1))
                              else return(c(1,2,3))
      })

如果apply() 应用于mimat,它会输出一个列表,而如果它应用于mimat2,它会输出一个矩阵。

【问题讨论】:

  • 你应该提供一个例子。您可以在这里寻找可能的解决方案:purrr.tidyverse.org
  • 简短回答:不,没有。将apply 与可能返回可变长度向量的函数一起使用是危险的。 for 循环要好得多(或者将矩阵强制转换为 data.frame,然后在可行的情况下调用 lapply)。
  • 您可以将返回向量包装在 list 中,如下所示:return(list(c(0,1))),然后您将始终得到一个列表。
  • @JohnPaul 如果你这样做,你会得到一个列表列表,这是一些东西,但仍然不是我想要的。无论如何,我想我会避免使用apply()

标签: r apply


【解决方案1】:

R4.1.0 在2021-03-06 上为apply() 添加了一个simplify 参数。

对于旧版本的 R,最好的选择可能是

lapply(seq_len(dim(minat)[2]), YourFunction)

【讨论】:

    【解决方案2】:

    我认为 purrr 包中的函数可能更适合您的目的,因为输出几乎是事先已知的。如果他们无法将输出与他们应该返回的数据结构相匹配,他们就会抛出错误(或者像文档所说的那样尝试死)。

    例如,map 函数总是返回一个列表,而它的变体 map_dblmap_lgl 等都返回一个指定类型的向量。

    在这个系列中还有另一个名为 modify 的函数,它保留了输入数据的结构(行号和列号)并且不改变数据结构,但是文档中说

    由于转换可以改变输入的结构;它是 您有责任确保转换产生有效的 输出。例如,如果您正在修改数据框,则 .f 必须 保留输入的长度。

    在您的第一个示例中,当您将匿名函数应用于 mimat 时,结果具有不同的长度,因此无法返回矩阵或数据框,因为我可以尝试使用 map 来获得相同的结果,而modify 未能保留输入的数据结构:

    library(purrr)
    
    map(as.data.frame(mimat), function(x) { 
      if (is.element(el = 1, x)) return(c(0,1))
      else return(c(1,2,3))
    })
    
    $V1
    [1] 0 1
    
    $V2
    [1] 1 2 3
    
    $V3
    [1] 1 2 3
    
    modify(as.data.frame(mimat), function(x) { 
      if (is.element(el = 1, x)) return(c(0,1))
      else return(c(1,2,3))
    })
    
    > Error in `[[<-.data.frame`(`*tmp*`, i, value = c(1, 2, 3)) :   
    > replacement has 3 rows, data has 2
    
    

    但如果您的第二个矩阵mimat2 函数的输出具有相等长度的行,因此可以使用称为map_dfcmap 变体来绑定输出。由于modify 再次失败导致输出数据结构与输出不同:

    map_dfc(as.data.frame(mimat2), function(x) { 
      if (is.element(el = 1, x)) return(c(0,1))
      else return(c(1,2,3))
    })
    
    # A tibble: 3 x 3
         V1    V2    V3
      <dbl> <dbl> <dbl>
    1     1     1     1
    2     2     2     2
    3     3     3     3
    
    modify(as.data.frame(mimat2), function(x) { 
      if (is.element(el = 1, x)) return(c(0,1))
      else return(c(1,2,3))
    })
    
    Error in `[[<-.data.frame`(`*tmp*`, i, value = c(1, 2, 3)) : 
      replacement has 3 rows, data has 2
    
    

    我必须将它们转换为数据框,否则它们被视为向量,并且该函数应用于每个元素而不仅仅是列。 这个简短的解释可能无法让你得到你想要的,但我希望它只是作为对其他一些具有固定输出的功能的介绍。 简而言之,它只归结为您应用于数据结构的函数,该函数必须以一种可以保留数据结构的方式转换数据。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2011-02-21
      • 2022-11-13
      • 2012-05-02
      • 1970-01-01
      • 2011-09-12
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多