使用apply类函数后保留维度:B[]赋值为何维度正确值错误?
R中数组赋值的差异与底层原理
B= 与 B[]= 的核心区别
B=:完全替换对象
直接将右侧表达式返回的对象(包括其维度、数据类型、属性等)整体赋值给B,覆盖B原本的所有属性。比如你用B=aperm(vapply(...), c(3,1,2))时,aperm调整后的数组维度会直接成为B的维度。B[]=:原地替换元素
不改变B已有的维度、属性,仅将右侧对象的元素按内存存储的原始顺序(即扁平化后的向量顺序)填充到B的内存空间中。要求右侧元素总数与B的元素总数一致,否则报错。
结合你的场景:
当你执行B[]=vapply(...)时,vapply返回的是n×p×S维度的数组,其内存存储顺序是先遍历n,再p,最后S;而你预先定义的B是S×n×p维度,内存顺序是先遍历S,再n,最后p。两者元素存储顺序不匹配,导致填充后值错位,结果错误。
m[] 保留维度的底层原理
在R中,对象的数据内容和**维度属性(dim)**是分开存储的:
- 当使用
m[]=时,R仅操作数据内容:它会将右侧对象“扁平化”为一维向量,然后按顺序复制到m的内存空间中; - 整个过程中,
m原本的dim、dimnames等属性完全保留,不会被右侧对象的属性覆盖; - 这也是
m[]=能维持原有维度的核心原因——它只修改数据,不碰属性。
更高效的实现方案
避免循环类操作(apply/vapply),用向量化矩阵乘法直接实现:
# 将A转置为m×S×p,再扁平化为m×(S*p)矩阵,与X(n×m)相乘后转成S×n×p数组 B <- array(X %*% aperm(A, c(2, 1, 3)), dim = c(S, n, p))
内容的提问来源于stack exchange,提问作者statstats
相关产品推荐
相关产品推荐

