为什么外部回收是一个应该闲置而不发出警告的载体?

Why is outer recycling a vector that should go unused and not throwing a warning?

最近使用了下面这行代码,估计会报错。令我惊讶的是,我得到了一个输出:

> outer(1:5,5:10,c=1:3,function(a,b,c) 10*a + 100*b + 1000*c)
     [,1] [,2] [,3] [,4] [,5] [,6]
[1,] 1510 3610 2710 1810 3910 3010
[2,] 2520 1620 3720 2820 1920 4020
[3,] 3530 2630 1730 3830 2930 2030
[4,] 1540 3640 2740 1840 3940 3040
[5,] 2550 1650 3750 2850 1950 4050

似乎正在对代码求值 outer(1:5,5:10,function(a,b) 10*a + 100*b)+1000*(1:3)。为什么是这样?作为后续行动,是否有任何明确的理由不发出警告?在我看来,输入这样的代码的用户可能期望输出涵盖所有 a、b 和 c 值。

这是基于 R 的回收规则的预期行为。它与 outer 本身无关,但如果您认为 outer 以某种方式跨边距应用函数,则可能会感到惊讶。

相反,outer 将两个向量 XY 作为其前两个参数。它需要 Xrep 请求 length(Y) 次。同样,它需要 Yrep 请求 length(X) 次。然后它只是在这两个长向量上运行你的函数 FUN,传递 long X 作为第一个参数,传递 long Y 作为第二个参数。 FUN 的任何其他参数都必须通过 ... 作为参数直接传递给外部(就像您对 c = 1:3 所做的那样)。

结果是一个单一的长向量,通过 length(Y).

将其 dim 属性作为 length(X) 的原始值写入而变成矩阵

现在,在您给出的具体示例中,X 有 5 个元素 (1:5),Y 有 6 个 (5:10)。因此,您的匿名函数在两个长度为 30 的向量和一个长度为 3 的向量上被调用。 R 的回收规则规定,如果回收向量恰好适合较长向量而没有部分回收,则不会发出警告。

要了解这一点,请使用您的匿名函数并在 outer 之外尝试使用两个长度为 30 的向量和一个长度为 3 的向量:

f <- function(a, b, c) 10*a + 100*b + 1000*c

f(1:30, 1:30, 1:3)
#>  [1] 1110 2220 3330 1440 2550 3660 1770 2880 3990 2100 3210 4320 2430
#> [14] 3540 4650 2760 3870 4980 3090 4200 5310 3420 4530 5640 3750 4860
#> [27] 5970 4080 5190 6300

3 很好地回收到 30,所以没有警告。

相反,如果您传递给 outer 的两个向量的长度乘积不是 3 的倍数,您 得到警告:

outer(1:5,6:10,c=1:3,function(a,b,c) 10*a + 100*b + 1000*c)
#>      [,1] [,2] [,3] [,4] [,5]
#> [1,] 1610 3710 2810 1910 4010
#> [2,] 2620 1720 3820 2920 2020
#> [3,] 3630 2730 1830 3930 3030
#> [4,] 1640 3740 2840 1940 4040
#> [5,] 2650 1750 3850 2950 2050
#> Warning message:
#> In 10 * a + 100 * b + 1000 * c :
#>   longer object length is not a multiple of shorter object length