2009-01-14 51 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);