将函数应用于具有分组变量的多维数组

Arh*_*ala 8 r

我有我认为是一个简单的问题,但我找不到合适的答案.我有一个多维数组v[x,y,z],我想使用分组变量(组)沿z维度向数组应用一个函数.这是一个例子(在R中):

v<-1:81
dim(v)<-c(3,3,9)
group<-c('a','a','a','b','b','b','c','c','c')
Run Code Online (Sandbox Code Playgroud)

鉴于分组变量有3个级别(a,bc),我正在寻找的结果(out)是一个维度为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) 
Run Code Online (Sandbox Code Playgroud)

我的问题是,是否有一种获得上述结果的一般方法,可以应用于大维数组和长分组向量.

flo*_*del 6

简单:

out <- apply(v, c(1, 2), by, group, sum)
Run Code Online (Sandbox Code Playgroud)

但是要以完全相同的顺序获取数据:

out <- aperm(apply(v, c(1, 2), by, group, sum), c(2, 3, 1))
Run Code Online (Sandbox Code Playgroud)


Sim*_*lon 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 ) }  )
Run Code Online (Sandbox Code Playgroud)

返回带有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
Run Code Online (Sandbox Code Playgroud)

我希望你能适应你的数据.


krl*_*mlr 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
Run Code Online (Sandbox Code Playgroud)

然后,您可以简单地附加您的分组...

vd$group <- rep(group, rep(3 * 3, length(group)))
Run Code Online (Sandbox Code Playgroud)

...并根据此分组进行划分:

daply(vd, .(group), function(df) { ... } )
Run Code Online (Sandbox Code Playgroud)

{ ... }每个组都会调用一次匿名函数,其中df包含与该组相对应的子数据帧。在这里,您可以使用类似的机制将数据重新组合并聚合到一个矩阵中。该函数应返回一个尺寸为 3x3x1 的数组,这些数组将通过 连接起来daply形成所需的结果。