2012-09-09 48 views
6

我有以下嵌套循环:遍历向量的笛卡尔积

for (x in xs) { 
    for (y in ys) { 
     # Do something with x and y 
    } 
} 

其中我想拉平,所以我想建立两个向量xsys的笛卡尔乘积并遍历结果。在Python中,这将是微不足道的:

for xy in product(xs, ys): 
    # x, y = xy[0], xy[1] 

但在R,我发现最简单的等同相当严峻:

xys <- expand.grid(xs, ys) 
for (i in 1 : nrow(xys)) { 
    xy <- as.vector(xys[i, ]) 
    # x <- xy[1], y <- xy[2] 
} 

当然必须有一个更好的办法,不是吗? (为了澄清,我不想遍历索引 ...我认为必须有一种方法可以直接迭代产品中的元组。)

回答

8

您可以使用apply函数将函数应用于数据框的每一行。只需用您的实际功能替换"your function"即可。

# example data 
xs <- rnorm(10) 
ys <- rnorm(10)  

apply(expand.grid(xs, ys), 1, FUN = function(x) {"your function"}) 

这是一个非常基本的例子。在这里,这两个值的连续总和计算:

apply(expand.grid(xs, ys), 1, FUN = function(x) {x[1] + x[2]}) 

下面是一个使用命名参数(xsys)的变体,而不是指数(x[1]x[2]):

myfun <- function(xs, ys) xs + ys 
arguments <- expand.grid(xs = rnorm(10), ys = rnorm(10)) 
apply(arguments, 1, function(x)do.call(myfun, as.list(x))) 
+0

@Konrad Rudolph:我放弃了我的答案。它没有错。我不确定它是否完全是您寻找的解决方案。 @flodel正确地说明了在混合输入类型中使用'apply'的问题。在这种情况下,您可以使用'as.numeric'将字符串转换为数字值。但只要您只使用数字矢量,就没有问题。 –

10

R有与Python不同的范例,不要期望它具有生成器或元组 - 我们有向量和索引。

这种方式,映射在笛卡尔积函数只需调用

outer(xs,ys,function(x,y) ...) 

,如果你想undim结果。

编辑:在壳体xsys是东西比基矢量更复杂,一个选择是使用指数,即

outer(seq(a=xs),seq(a=ys),function(xi,yi) ... xs[[xi]]/ys[xi,]/etc. ...) 

,或者使用地图上的位的手工制作的产品的功能mapply

mapply(function(x,y) ...,xs,rep(ys,each=length(xs))) 
+0

我不关心不同的范例。我很担心我的代码中索引变量的普遍性。据我了解R,大多数/所有这些应该是不必要的。你的示例代码看起来像我搜索它的行为是错误的:'outer(1:2,3:4,function(x,y){print(sprintf('%d,%d', x,y))}' - 这会打印一个数组*和*结果矩阵 - 所以我不知道如何重写我的循环在这里工作......(我不知道你的意思是“undim” ) –

+0

Uuh,前面的评论是愚蠢的,矩阵只是'outer'的返回值,不过,我仍然不确定如何调整它以替代我的嵌套循环,因为'x'和'y'是向量,而不是标量。不幸的是,我确实需要标量。 –

+0

@KonradRudolph好的,扩展。 – mbq