【问题标题】:Implementation of standard recycling rules执行标准回收规则
【发布时间】:2012-03-09 06:10:13
【问题描述】:

R 的一个很好的特性与它固有的矢量化特性有关,它是第 2.2 节中An Introduction to R 中描述的回收规则。

出现在同一个表达式中的向量不必都具有相同的长度。如果不是,则表达式的值是一个与表达式中出现的最长向量具有相同长度的向量。表达式中较短的向量被回收尽可能频繁地(可能是部分地),直到它们与最长向量的长度相匹配。特别是简单地重复一个常数。

大多数标准函数都使用它,但这样做的代码隐藏在底层 C 代码中。

是否有一种规范的方法可以完全在 R 代码中实现函数的标准回收规则?也就是说,给定一个类似

的函数
mock <- function(a, b, c) {
    # turn a, b, and c into appropriate recycled versions

    # do something with recycled a, b, and c in some appropriately vectorized way
}

其中abc 是向量,可能具有不同的长度和未知的类型/类别,是否有一种规范的方法来获取根据标准回收规则回收的一组新向量?特别是,我不能假设“做某事”步骤本身会进行适当的回收,所以我需要自己提前做。

【问题讨论】:

    标签: r


    【解决方案1】:

    我以前用过这个,

    expand_args <- function(...){
      dots <- list(...)
      max_length <- max(sapply(dots, length))
      lapply(dots, rep, length.out = max_length)
    }
    

    【讨论】:

    • 从 R 3.2 开始,您可能希望使用 lengths(dots) 而不是 sapply(dots, length)
    【解决方案2】:

    我可能会使用rep()length.out 参数来完成大部分实际工作。

    这是一个创建better.data.frame() 函数的示例(它实际上应该称为"better".data.frame()),它对作为参数传递的向量的长度没有任何限制。在这种情况下,我将所有向量回收到最长向量的长度,但您显然可以对其进行调整以满足您自己的回收需求!

    better.data.frame <- function(...) {
        cols <- list(...)
        names(cols) <- sapply(as.list(match.call()), deparse)[-1]
    
        # Find the length of the longest vector
        # and then recycle all columns to that length.
        n <- max(sapply(cols, length))
        cols <- lapply(cols, rep, length.out = n)
    
        as.data.frame(cols)
    }
    
    # Try it out
    a <- Sys.Date() + 0:9
    b <- 1:3
    c <- letters[1:4]
    
    data.frame(a,b,c)
    # Error in data.frame(a, b, c) : 
    #   arguments imply differing number of rows: 10, 3, 4
    
    better.data.frame(a,b,c)
    #             a b c
    # 1  2012-02-17 1 a
    # 2  2012-02-18 2 b
    # 3  2012-02-19 3 c
    # 4  2012-02-20 1 d
    # 5  2012-02-21 2 a
    # 6  2012-02-22 3 b
    # 7  2012-02-23 1 c
    # 8  2012-02-24 2 d
    # 9  2012-02-25 3 a
    # 10 2012-02-26 1 b
    

    【讨论】:

    • 您可以修改您的n &lt;- 以处理最长参数不是第一个的情况。 n &lt;- max(unlist(lapply(list(a,b,c),length),max) 并添加 a &lt;- rep(a, length.out = n)
    • @Justin -- 谢谢。我刚刚开始这样做,并且还将函数泛化为采用任意数量的参数。如果您(或其他任何人)看到更好的方法让我从函数调用中提取所提供参数的名称,请告诉我。这正是我在飞行中想出的......
    【解决方案3】:

    数值参数的一个短而脏的方法是依赖 cbind 的自动回收。例如:

    f.abc <- function(a,b,c) {
    
         df.abc <- as.data.frame( suppressWarnings( cbind(a=a, b=b, c=c) ) )
    
         #Then use, for example, with() to use a, b and c inside the data frame, 
         #or apply(df.abc,1, ...) 
    }
    

    不过,它确实在很大程度上依赖于没有其他合理的警告原因。

    【讨论】:

      猜你喜欢
      • 2019-09-11
      • 2020-04-02
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多