2011-11-17 18 views
1

好的,按照要求,我會添加更多的信息,以便您明白爲什麼簡單的矢量操作是不可能的。用幾句話來解釋並不容易,但讓我們拭目以待。我在2D空間上有大量的點數。 我把我的空間分成一個給定的分辨率,比如100米。我不確定是否強制的主循環(歡迎任何替代方法)是通過每個包含至少2個點的單元格/像素(現在我正在使用spatstat包中的方法quadratcount)。 在這個循環中,因此對於這些非空單元格中的每一個,我必須找到並保留最多10個彼此相距3米以內的男 - 女對。 3米長的緩衝區可以使用spatstat中的「光盤」功能完成。要選擇落入緩衝區內的點,可以使用SDMTools包中的方法pnt.in.poly。所有這些都是因爲像素的最大容量不能超過。因爲在每個單元格中可能有數百或數千個點,所以我試圖找到一種巧妙的方法來使用另一個循環/類似的方法來:1)每次點擊每個點2)創建一個具有不同性別的選擇點3)將最接近的男 - 女(0-1)對保存在另一個數據框(稱爲new_colonies)中4)從數據框中刪除這些點,使其縮小並且不必再考慮它們5)數據幀到達10行會停止所有操作並轉到下一個單元格(從而跳過所有剩餘的點,下面是我開發的用於在每個單元格內運行的代碼(現在需要太長時間):在R循環中動態刪除元素

head(df,20 ):

X  Y Sex ID 
2 583058.2 2882774 1 1 
3 582915.6 2883378 0 2 
4 582592.8 2883297 1 3 
5 582793.0 2883410 1 4 
6 582925.7 2883397 1 5 
7 582934.2 2883277 0 6 
8 582874.7 2883336 0 7 
9 583135.9 2882773 1 8 
10 582955.5 2883306 1 9 
11 583090.2 2883331 0 10 
12 582855.3 2883358 1 11 
13 582908.9 2883035 1 12 
14 582608.8 2883715 0 13 
15 582946.7 2883488 1 14 
16 582749.8 2883062 0 15 
17 582906.4 2883317 0 16 
18 582598.9 2883390 0 17 
19 582890.2 2883413 0 18 
20 582752.8 2883361 0 19 
21 582953.1 2883230 1 20 

每一個小區,我必須按我上面解釋的運行裏面的東西..

for(i in 1:dim(df)[1]) {

new_colonies <- data.frame(ID1=0,ID2=0,X=0,Y=0) 

discbuff <- disc(radius, centre=c(df$X[i], df$Y[i])) 

#define the points and polygon 
pnts = cbind(df$X[-i],df$Y[-i]) 
polypnts = cbind(x = discbuff$bdry[[1]]$x, y = discbuff$bdry[[1]]$y) 
out = pnt.in.poly(pnts,polypnts) 
out$ID <- df$ID[-i] 

if (any(out$pip == 1)) { 

pnt.inBuffID <- out$ID[which(out$pip == 1)] 
cond <- df$Sex[i] != df$Sex[pnt.inBuffID] 

if (any(cond)){ 

eucdist <- sqrt((df$X[i] - df$X[pnt.inBuffID][cond])^2 + (df$Y[i] - df$Y[pnt.inBuffID][cond])^2) 

IDvect <- pnt.inBuffID[cond] 
new_colonies_temp <- data.frame(ID1=df$ID[i], ID2=IDvect[which(eucdist==min(eucdist))], 
       X=(df$X[i] + df$X[pnt.inBuffID][cond][which(eucdist==min(eucdist))])/2, 
       Y=(df$Y[i] + df$Y[pnt.inBuffID][cond][which(eucdist==min(eucdist))])/2) 

new_colonies <- rbind(new_colonies,new_colonies_temp) 

if (dim(new_colonies)[1] == maxdensity) break 

} 
} 
} 

new_colonies <- new_colonies[-1,] 

任何幫助表示讚賞! 謝謝 弗朗切斯科

+1

歡迎來到SO,請嘗試給我們一個可重現的例子,例如通過使用'dput(head(df,10))'。此外,瞭解一些特定情況會很好,因爲你可能甚至不需要循環,但可以通過矢量化的方式解決它。 –

+2

可能試試?子集 – aatrujillob

+0

我會盡快列出我需要用相關代碼做的所有事情,只要它允許我放棄我自己的問題並在這裏發帖......很快檢查一下,如果你能幫助我,那將很棒! – Francesco

回答

4

在你的情況我就不會擔心刪除點,你跳,跳過是關鍵的事情。我也不會像你似乎正在做的那樣逐個構建一個新的數據框架。這兩件事都讓你感到很沮喪。有一個選擇向量效率更高(可能是data.frame的一部分,您事先設置爲FALSE)。

df$sel <- FALSE 

現在,當你通過你設置df $ sel爲TRUE爲每個項目你想保持。當你找到10時,跳到下一個單元格。隨着時間的推移刪除值將會耗費大量時間並且會佔用大量內存,同時還會慢慢增加新的數據幀。當你完成所有的工作時,你可以根據選擇欄來選擇你的數據。

df <- df[ df$sel, ] 

(或者也許是爲了在這一點上data.frame副本)

您可能還需要使用dist函數來計算距離的矩陣。

?dist

「該函數計算,並返回通過使用指定的距離度量以計算數據矩陣的行之間的距離計算的距離矩陣。」

+0

我會盡快發佈我的答案,並解釋我正在嘗試做什麼。請檢查它是否可以...謝謝 – Francesco

+0

非常感謝...我會盡力的。因此,基本上使用rbind一次一點點地構建一個數據框在R中是耗時和緩慢的。所以你說我無法擺脫2個for循環(一個要經過每個網格單元和一個(上面的代碼)通過該單元格中的每個點....?我有關於此數據框堆棧過程的另一個問題,但我將在稍後的另一節中發佈它。 – Francesco

+0

最好保持外部循環。內部循環可能能夠大多是矢量化的。你看了dist嗎? – John

1

我不完全清楚爲什麼你循環。如果你可以描述你正在檢查什麼樣的條件,那麼可能會有一個很好的矢量化的方法。

但是,作爲一個非常簡單的修復方法,您是否考慮過向後循環數據幀?

+0

爲什麼我要向後循環?這會讓它變得更快嗎? – Francesco

+0

如果您向後循環並刪除行,它不一定有效,但以這種方式您不會跳過行。 – Dason

+0

但在這種情況下,我的問題是,因爲一個循環需要一個索引範圍,如果我在循環中刪除一些行,我會收到一個錯誤,該索引超出範圍(因爲數據框的維度會發生變化) ? – Francesco

2

我假設你正在做的事情足夠複雜的實際需要循環...

因此,這裏是一個很簡單的辦法:第一隻收集要刪除的行(或保留),然後之後刪除行。通常情況下,由於您不會在每次循環迭代中修改data.frame,因此速度也會更快。

df <- generateTheDataFrame() 

keepRows <- rep(TRUE, nrow(df)) 
for(i in seq_len(nrow(df))) { 
    rows <- findRowsToDelete(df, df[i,]) 
    keepRows[rows] <- FALSE 
} 

# Delete afterwards 
df <- df[keepRows, ] 

...如果你真的需要在每次迭代收縮的數據的工作,只是改變for循環部分:

for(i in seq_len(nrow(df))) { 
    if (keepRows[i]) { 
     rows <- findRowsToDelete(df[keepRows, ], df[i,]) 
     keepRows[rows] <- FALSE 
    } 
} 
+0

即使您必須在行上運行循環才能獲取您稍後將檢查是否要保留該行的值,最好在事後進行檢查。這些例子中的任何一個都會比後續的矢量化選擇帶來更多的時間。 – John

+0

@john - 確實如此,但前提是這樣做是可行的。沒有更多的信息,這只是另一個猜測 - 儘管是一個好的;-)。向量化是偉大的,但並不總是可能的(有條件的累積總和在腦海中浮現)。 – Tommy