2009-01-14 82 views
12

早些时候,我回答了我自己关于在R中向量中思考的问题。但是现在我又遇到了另一个我不能'矢量化'的问题。我知道矢量更快,循环速度更慢,但我不知道如何在矢量方法中执行此操作:对此做一个完整的边际分析。我需要一次删除一个元素,并'数值'的数据框,然后我需要通过删除只有下一个元素再次进行迭代。然后再次......再次......这个想法是对我的数据的一个子集进行完全边际分析。总之,我无法想象如何以矢量有效的方式做到这一点。向量化我的思维:R中的向量运算

我已经缩短了代码的循环部分下来,它看起来是这样的:

for (j in my.data$item[my.data$fixed==0]) { # <-- selects the items I want to loop 
              #  through 
    my.data.it <- my.data[my.data$item!= j,] # <-- this kicks item j out of the list 
    sum.data <-aggregate(my.data.it, by=list(year), FUN=sum, na.rm=TRUE) #<-- do an 
                     # aggregation 

    do(a.little.dance) && make(a.little.love) -> get.down(tonight) # <-- a little 
                    # song and dance 

    delta <- (get.love)           # <-- get some love 
    delta.list<-append(delta.list, delta, after=length(delta.list)) #<-- put my love 
                    # in a vector 
} 

所以很明显,我砍死了一堆东西在中间,只是使其不太笨拙。目标是使用更高效的矢量去除j循环。有任何想法吗?

+0

@joran:有必须是编辑30个月以上问题的奖项。 :) – Iterator 2011-08-10 01:29:22

+1

一些版本的死灵法师,也许? – 2011-08-10 15:15:32

回答

7

这似乎是另一种非常R型的方式来产生总和。生成一个与您的输入向量一样长的向量,除了n个元素的重复和之外什么也不包含。然后,从总和矢量中减去原始矢量。结果是:一个矢量(isums),其中每个条目是您的原始矢量,而不是第i个元素。

> (my.data$item[my.data$fixed==0]) 
[1] 1 1 3 5 7 
> sums <- rep(sum(my.data$item[my.data$fixed==0]),length(my.data$item[my.data$fixed==0])) 
> sums 
[1] 17 17 17 17 17 
> isums <- sums - (my.data$item[my.data$fixed==0]) 
> isums 
[1] 16 16 14 12 10 
0

这是没有答案,但我不知道任何见解在于这个方向:

> tapply((my.data$item[my.data$fixed==0])[-1], my.data$year[my.data$fixed==0][-1], sum) 

tapply产生统计表(资金,在这种情况下,第三个参数)给出的参数组合第二个参数。例如,

2001 2003 2005 2007 
1 3 5 7 

[-1]符号会从选定的行中删除观察(行)一个观察值。所以,你可以循环,每个循环使用[-i]记住

for (i in 1:length(my.data$item)) { 
    tapply((my.data$item[my.data$fixed==0])[-i], my.data$year[my.data$fixed==0][-i], sum) 
} 

保存,如果你有1只观察任何年,然后通过连续tapply调用返回的表不会有相同的列数。 (即,如果你剔除了2001年唯一的观察结果,那么2003年,2005年和2007年将只返回列)。

8

奇怪的是,在R中学习矢量化是帮助我习惯基本函数式编程的原因。一个基本的技术将是确定的循环内您的操作作为一个函数:

data = ...; 
items = ...; 

leave_one_out = function(i) { 
    data1 = data[items != i]; 
    delta = ...; # some operation on data1 
    return delta; 
} 


for (j in items) { 
    delta.list = cbind(delta.list, leave_one_out(j)); 
} 

向量化,你要做的就是与sapply映射函数替换for循环:

delta.list = sapply(items, leave_one_out);