为什么外部回收是一个应该闲置而不发出警告的载体?
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
将两个向量 X
和 Y
作为其前两个参数。它需要 X
和 rep
请求 length(Y)
次。同样,它需要 Y
和 rep
请求 它 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
最近使用了下面这行代码,估计会报错。令我惊讶的是,我得到了一个输出:
> 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
将两个向量 X
和 Y
作为其前两个参数。它需要 X
和 rep
请求 length(Y)
次。同样,它需要 Y
和 rep
请求 它 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