Matlab 矩阵返回向量的逻辑索引-需要初始化吗?

Matlab 矩阵返回向量的逻辑索引-需要初始化吗?,matlab,matrix,indexing,Matlab,Matrix,Indexing,在Matlab中,为矩阵创建逻辑索引时,似乎需要初始化NaN(或其他?)矩阵以保留相对位置。例如,考虑下面的例子: clear all; close all; clc; Data = [1 2 3 4; 3 40 5 6; 5 6 7 8]; ind = logical([0 0 0 0;0 1 1 0;0 1 0 0]); tic x1 = NaN * ones(3,4); y1 = NaN * ones(1,4); y2 = y1; x1(ind) = Data(ind); % wr

在Matlab中,为矩阵创建逻辑索引时,似乎需要初始化NaN(或其他?)矩阵以保留相对位置。例如,考虑下面的例子:

clear all; close all; clc;

Data = [1 2 3 4; 3 40 5 6; 5 6 7 8];
ind = logical([0 0 0 0;0 1 1 0;0 1 0 0]); 

tic
x1 = NaN * ones(3,4); 
y1 = NaN * ones(1,4); y2 = y1;
x1(ind) = Data(ind); % writing to pre-allocated NaN matrix (necessary?)
y1(1:4) = nanmean(x1,1); % take NaN-mean - good result
toc

% Can we get rid of x1? The following obviously does not work:
y2(1:4) = nanmean(Data(ind),1);

如上代码所述,
Data(ind)
将返回一个向量,而不保留原始大小。到目前为止,我唯一的解决方案是使用
x1
,它被初始化为具有正确的大小。那么:是否需要创建一个完整的(
x1
)NaN矩阵?有没有关于如何避免这种情况的想法?我不是在寻找for循环,因为我正在尝试加快这段代码的速度。

简短回答:是的,对于完整的矩阵,需要预先初始化以获得正确的矩阵大小和形状


如果担心浪费内存,可以使用
sparse
命令生成稀疏矩阵。在这种情况下,您需要将逻辑索引分解为单独的行索引和列索引。

您可以使用
accumarray
来拯救您自己,但您仍然需要为输出预分配,我希望这是可以的,因为您无论如何都要使用该输出,否则您将不需要它。对于您的问题案例,您可以在此处使用两种AppProach

方法#1

[~,c] = find(ind); %// get column indices
out = NaN(1,size(Data,2)); %// pre-allocate for output

calc_result = accumarray(c,Data(ind),[], @mean)  %// get mean calculated results
array1 = 1:max(c)
vind = ismember(array1,c) %// valid indices
out(array1(vind)) =  calc_result(vind)
方法#2

[~,c] = find(ind); %// get column indices OR try c = ceil(find(ind)/size(ind,1))
vind = c(diff([0 ; c])~=0);   %// valid indices

out(1,1:size(Data,2)) = NaN; %// pre-allocate for output
calc_result = accumarray(c,Data(ind),[], @mean); %// get mean calculated results
out(vind) =  calc_result(vind);

使用方法1完成代码,以便与受信任的输出进行比较-

输出-

Data =
     1     2     3     4
     3     4     5     6
     5     6     7     8
ind =
     0     0     0     0
     0     1     0     0
     0     1     0     1
y1 =
   NaN     5   NaN     8
out =
   NaN     5   NaN     8

谢谢你的快速回复,迪伦。我有点担心记忆力,尽管我没有这样想过。基本上,分配和操作需要时间进行更大的分析,我想减少分析。虽然稀疏可以很方便,但我认为按照建议从逻辑到索引的转换将需要更多的计算时间。此外,稀疏矩阵实际上可能更大(请参阅),并且对其他元素错误地假定为0。必须在某个点为矩阵分配内存。您有两种选择--稀疏矩阵或完整矩阵。如果选择完整矩阵,则无论何时分配内存,都需要相同的内存量(以及相同的分配时间)。但是,我没有意识到您的最终目标是执行
nanmean
——使用
accumarray
绝对是一个好的解决方案。最初的解决方案需要对整个矩阵进行双重分配—一次是
数据
,一次是
x1
,其中
x1
大部分是
NaN
填充的副本。如果问题不清楚,我深表歉意。我打算删除额外的步骤(
x1
)。据我所知,Divakar的解决方案只存储相关项(在
c
),我同意Sparse可以做到这一点,但我没有办法处理生成的稀疏矩阵,因为它在其他位置假定为零。我知道预分配现在只是部分删除,但这是一个巨大的改进。我们能否更改
数据
,以便引导我们获得输出?我希望
数据
可用于多个不同的选择。所以我希望它不被覆盖。你说得对。总体而言,代码在计算平均值的
accumarray
行上花费1.5秒。包含元素数的
accumarray
行花费0.5s,
总和(ind(:,1:numel))
花费0.2s。因此,这确实是一个进步。分配输出变量的行只需0.25秒。感谢您的所有时间和努力,非常感谢。我删除了我之前的评论,因为时间信息似乎不正确,因此与其他读者无关/混淆。你的解决方案,特别是#2,效果很好。
Data =
     1     2     3     4
     3     4     5     6
     5     6     7     8
ind =
     0     0     0     0
     0     1     0     0
     0     1     0     1
y1 =
   NaN     5   NaN     8
out =
   NaN     5   NaN     8