我有一个矩阵A,我想找到每列最后两个非NaN值。
例如,生成以下矩阵:
A = [NaN, 3, NaN; 5 5 5; NaN 1 9; 4 1 4; NaN 6 NaN; 6 2 9]我想得到以下结果:
B =
4 6 4
6 2 9我怎样才能以最有效的方式做到这一点,而不需要for-循环?
我尝试了以下方法:[row,col,v] = find(A,3,'last'),但是它返回了一些我不理解的内容:
row =
5
6
col =
3
3
v =
NaN
9发布于 2018-03-16 15:54:41
find的第三个参数实际上找到了非零的实际位置。它按列进行搜索,并返回最后三个非零值及其实际值的行和列位置。NaN在技术上是非零的,这就是为什么它会返回给您。
首先,用NaN查找矩阵中所有不是find的位置。
[I,J] = find(~isnan(A));这将返回非NaN值的行和列位置。我们现在得到:
>> [I,J]
ans =
2 1
4 1
6 1
1 2
2 2
3 2
4 2
5 2
6 2
2 3
3 3
4 3
6 3我们可以看到一个很好的模式形成。左列显示不是NaN的所有行位置,右边列告诉您是哪一列。
接下来,我们可以做的是对第二列,找到从一列到另一列的转换点。这将给出最后一个元素的位置,这些元素不是每个列的NaN。然后,我们可以减去这些指数1,给出第二个不是NaN的最后一个元素的位置。我们可以使用diff函数来帮助我们做到这一点,并检查距离何时为非零。请注意,这将使输出的大小减少1,因为我们正在计算成对的距离,但只需在末尾放置1,因为这意味着最后一列的结束,这是我们想要找到列的最后两个元素的地方:
>> d = [diff(J) ~= 0; 1];
>> [J d]
ans =
1 0
1 0
1 1
2 0
2 0
2 0
2 0
2 0
2 1
3 0
3 0
3 0
3 1现在,让我们以diff的输出为例,并将所有内容都提高1:
d(1:end-1) = d(1:end-1) | d(2:end);这将使我们能够标记每个列的第二个最后一个元素来捕获:
>> [I J d]
ans =
2 1 0
4 1 1
6 1 1
1 2 0
2 2 0
3 2 0
4 2 0
5 2 1
6 2 1
2 3 0
3 3 0
4 3 1
6 3 1最后但同样重要的是,我们现在对上述矩阵的前两列进行采样,其中第三列为非零,将它们转换为线性索引,并对我们的矩阵进行采样。为此,我们将使用reshape和sub2ind的组合:
loc = d ~= 0;
out = reshape(A(sub2ind(size(A), I(loc), J(loc))), 2, size(A,2));因此:
>> out
out =
4 6 4
6 2 9因此,最后的准则是:
[I,J] = find(~isnan(A));
d = [diff(J) ~= 0; 1];
d(1:end-1) = d(1:end-1) | d(2:end);
loc = d ~= 0;
out = reshape(A(sub2ind(size(A), I(loc), J(loc))), 2, size(A,2));警告
这假设每个列至少有两个元素不是NaN。
发布于 2018-03-16 15:49:56
如下所示:
A = [NaN, 3, NaN; 5 5 5; NaN 1 9; 4 1 4; NaN 6 NaN; 6 2 9]
N=2; %last 2
IsOK=~isnan(A);
[~,I]=sort(IsOK);
Iok=I(end-N+1:end,:); %get last N
LinearIndxs=sub2ind(size(A), Iok, repmat(1:size(A,2),N,1));
Result=A(LinearIndxs)https://stackoverflow.com/questions/49324057
复制相似问题