我想要一个沿给定轴标准化数组的函数。基本上,我想写的是:
apply(X, axis, normalize)
它应该按行,列,......或沿着第n维标准化我的数组。
这听起来像是一个非常普遍的问题,但R似乎无法在不使用怪癖的情况下解决它。
考虑以下矩阵和函数:
> m = matrix(1:4,nrow=2,dimnames=list(c('a','b'),c('x','y')))
> m
x y
a 1 3
b 2 4
normalize=function(X) {
X = X - mean(X)
X = X/sd(X)
return(X)
}
如果我使用带有轴编号的apply()
,则会出现以下情况:
> apply(m, 2, normalize)
x y
a -0.7071068 -0.7071068
b 0.7071068 0.7071068
这里一切都很好
> apply(m, 1, normalize)
a b
x -0.7071068 -0.7071068
y 0.7071068 0.7071068
这里,矩阵已被转置(这是我不想要的)。我想保留n维数组的原始尺寸。
不工作的可能答案是:
t()
,跨行应用它然后转置回来:这不适用于多维数组if
子句:解决方案通常适用,不仅适用于某些硬编码案例 编辑:根据Roland的建议,我将使用以下函数代替apply
:
array_apply = function(X, along, FUN) {
X = as.array(X)
ndim = c(1:length(dim(X)))
preserveAxes = ndim[ndim != along]
orderAxes = c(along, preserveAxes)
X = apply(X, preserveAxes, FUN)
return(aperm(X, orderAxes))
}
的行为方式如下:
> m = matrix(1:4,nrow=2,dimnames=list(c('a','b'),c('x','y')))
> array_apply(m,1,normalize)
x y
a -0.7071068 -0.7071068
b 0.7071068 0.7071068
> array_apply(m,2,normalize)
x y
a -0.7071068 0.7071068
b -0.7071068 0.7071068
答案 0 :(得分:3)
让我们用一个更好的例子来看看会发生什么:
m = matrix(c(1,2,7,10,12,18),nrow=2)
# [,1] [,2] [,3]
#[1,] 1 7 12
#[2,] 2 10 18
apply(m, 1, scale)
# [,1] [,2]
#[1,] -1.02888681 -1
#[2,] 0.06052275 0
#[3,] 0.96836405 1
如您所见,scale
应用于矩阵行,结果向量组合为结果矩阵的列。
apply(m, 2, scale)
# [,1] [,2] [,3]
#[1,] -0.7071068 -0.7071068 -0.7071068
#[2,] 0.7071068 0.7071068 0.7071068
现在scale
应用于矩阵列,但结果向量再次组合为结果矩阵的列。事实上,help("apply")
:
如果每次调用FUN都返回一个长度为n的向量,则apply返回 如果n> 1,则为维数c(n,dim(X)[MARGIN])的数组。 1。
修改:
如果您执行以下操作,则可以避免此问题:
(m-apply(m,1,mean))/apply(m,1,sd)
[,1] [,2] [,3]
[1,] -1.028887 0.06052275 0.9683641
[2,] -1.000000 0.00000000 1.0000000