2013-04-21 53 views
8

我有我認爲會是一個簡單的問題,但我一直無法找到合適的答案。我有一個多維數組v[x,y,z],我想用一個分組變量(組)將一個函數應用到維度上的數組。下面是一個例子(在R):將函數應用到具有分組變量的多維數組中

v<-1:81 
dim(v)<-c(3,3,9) 
group<-c('a','a','a','b','b','b','c','c','c') 

鑑於分組變量有3個級別(一個bÇ),結果()我正在尋找是一個尺寸爲3x3x3的數組。我可以得到出使用以下代碼爲上面的例子:

out1<-apply(v[,,c(1:3)],c(1,2),sum) 
out2<-apply(v[,,c(4:6)],c(1,2),sum) 
out3<-apply(v[,,c(7:9)],c(1,2),sum) 

library(abind) 
out<-abind(out1, out2, out3, along=3) 

我的問題是如果在獲取上述的結果,這可以應用到大尺寸的陣列和長分組矢量的一個通用方法。

+1

在@krlmlr的回答下給出您的評論,如果您能更準確地描述您正在使用的數據,那將會更好。開發一個答案是令人沮喪的,實際上,你所擁有的數據與你所描述的非常不同,所以*不起作用*! – 2013-04-21 21:55:33

+2

由於您正在處理遙感數據,因此我需要查看爲這種數據優化的''raster'包,'stack'和'calc'函數。 – 2013-04-21 21:57:17

回答

2

這是容易得多,如果你的數據被格式化爲數據幀:

library(plyr) 
vd <- adply(v, 1:3) 
head(vd) 

    X1 X2 X3 V1 
1 1 1 1 1 
2 2 1 1 2 
3 3 1 1 3 
4 1 2 1 4 
5 2 2 1 5 
6 3 2 1 6 

然後,您可以簡單地連接您的分組...

vd$group <- rep(group, rep(3 * 3, length(group))) 

...和分裂根據本分組:

daply(vd, .(group), function(df) { ... }) 

匿名函數{ ... }將一次每個G被稱爲組,其中df包含對應於該組的子數據幀。在這裏,您可以使用類似的機制將數據重新組合並聚合成矩陣。該函數應該返回一個尺寸爲3x3x1的數組,這些將被連接daply以形成所需的結果。

+0

感謝您的時間Krlmlr。不幸的是,這並不能解決我的問題。我給出的例子是使用一個小型「模型」。我使用的陣列是非常大的遙感數據,由此陣列中的每個矩陣可以表示1000 x 1000點空間矩陣乘以包含多年的天數(z維度)。我需要找出每個月1000 x 1000點空間矩陣中每個點的平均值。在隨後的分析中,我還需要維護數據的數組結構。感謝你的寶貴時間。 – Arhopala 2013-04-21 21:27:42

6

簡單:

out <- apply(v, c(1, 2), by, group, sum) 

但要獲得的數據完全相同的順序,只要你想:

out <- aperm(apply(v, c(1, 2), by, group, sum), c(2, 3, 1)) 
+0

'by'是什麼意思? – krlmlr 2013-04-21 21:58:24

+0

這是一個函數,查看'?by'。 – flodel 2013-04-21 21:59:07

+0

非常感謝Flodel,我非常感謝你的幫助。 – Arhopala 2013-04-21 22:08:30

5

使用包光柵可能更適合您的需求。它有一些優化的代碼用於處理遙感數據,負責處理塊。考慮下面這個例子:

## Make 12 rasters, maybe one for each month of the year 
for(i in seq(12)){ 
    assign(paste0("r" , i) , raster(matrix(runif(1e3) , nrow = 1e2))) 
} 

## Create a raster stack from these 
rS <- stack(mget(paste0("r",1:12) , envir = .GlobalEnv)) 

## Use calc to get mean, using by to group by a variable 
## In this example I use the vector (1,1,1,2,2,2,3,3,3,4,4,4) 
## meaning I get means for the first 3 rasters, then the next 3 etc 
## So I get a mean for each quarter 
rMean <- calc(rS , fun = function(x){ by(x , c(rep(1:4 , each=3)) , mean) } ) 

它返回一個光柵磚4層(一個平均每個季度):

class  : RasterBrick 
dimensions : 100, 10, 1000, 4 (nrow, ncol, ncell, nlayers) 
resolution : 0.1, 0.01 (x, y) 
extent  : 0, 1, 0, 1 (xmin, xmax, ymin, ymax) 
coord. ref. : NA 
data source : in memory 
names  :   X1,   X2,   X3,   X4 
min values : 0.02096586, 0.04015260, 0.04704145, 0.05884161 
max values : 0.9727491, 0.9303025, 0.9804486, 0.9934670 

我希望你能適應這樣您的數據。

+0

非常感謝Simon,它對於柵格數據的使用看起來很有趣。我要用一些我擁有的數據集來測試它! – Arhopala 2013-04-21 23:24:50

+0

@Arhopala測試結果如何?這個解決方案是否適合你?或者你需要它更高效/更快? – 2013-04-23 13:07:44

+0

嗨西蒙,抱歉有點遲緩的回覆,但忙於提交一份手稿。我有時間嘗試一下你的建議,它工作正常。然而,這比Flodel的建議慢一點。我在Flodel's的兩個用戶時間和14.976的26.0 100x100矩陣上爲您的19.086運行了一個system.time。目前我正在將衛星圖像轉換爲HDF5或NetCDF,然後導入到R進一步分析。謝謝你的幫助。 – Arhopala 2013-04-24 00:56:44