Matlab 在每列矩阵中查找最后两个非唯一观测值

Matlab 在每列矩阵中查找最后两个非唯一观测值,matlab,find,unique,Matlab,Find,Unique,我有一个矩阵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'),但这返回了一些我不理解的内容:

我有一个矩阵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
这就是为什么:

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)
这就是为什么:

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)

find
的第三个参数实际查找非零的实际位置。它按列搜索并返回最后三个非零值的行和列位置及其实际值
NaN
在技术上是非零的,这就是它返回给您的原因

首先,用
find
查找矩阵中所有非
NaN
的位置:

[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
。我们可以使用该函数来帮助我们做到这一点,并检查距离是否为非零。请注意,这将使输出的大小减小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
最后但并非最不重要的一点是,我们现在对上述矩阵的前两列进行采样,其中第三列为非零,将其转换为线性指数并对矩阵进行采样。为此,我们将使用和的组合:

loc = d ~= 0;
out = reshape(A(sub2ind(size(A), I(loc), J(loc))), 2, size(A,2));
因此:

因此,最终代码是:

[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

find
的第三个参数实际查找非零的实际位置。它按列搜索并返回最后三个非零值的行和列位置及其实际值
NaN
在技术上是非零的,这就是它返回给您的原因

首先,用
find
查找矩阵中所有非
NaN
的位置:

[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
。我们可以使用该函数来帮助我们做到这一点,并检查距离是否为非零。请注意,这将使输出的大小减小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
最后但并非最不重要的一点是,我们现在对上述矩阵的前两列进行采样,其中第三列为非零,将其转换为线性指数并对矩阵进行采样。为此,我们将使用和的组合:

loc = d ~= 0;
out = reshape(A(sub2ind(size(A), I(loc), J(loc))), 2, size(A,2));
因此:

因此,最终代码是:

[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

@SardarUsama,没错。我在做accumarray,然后改成了这个。虽然OP的例子没有描述任何唯一性,但我担心OP实际上可能希望每列中都有唯一的值。(问题删去的部分)@SardarUsama,仅在标题中注明。实际问题提到他想要最后两个非NaN值。我认为他的问题内容是正确的,并删去了标题。如果OP真的需要最后两个唯一值,那么输出矩阵就有可能不再合适,您将不得不求助于循环和单元格数组,或者可能求助于
struct
,因为很可能有一个列具有非NaN值,但只有一个唯一值。@JohnAndrews如果是这种情况,那好吧。代码将自动对最后两行进行采样,因此代码不应更改。我不知道你担心什么。@JohnAndrews好的,那需要重新设计一下。。。。“让我来解决这个问题。”萨达鲁萨马说得对。我在做accumarray,然后改成了这个。虽然OP的例子没有描述任何唯一性,但我担心OP实际上可能希望每列中都有唯一的值。(问题删去的部分)@SardarUsama,仅在标题中注明。实际问题提到他想要最后两个非NaN值。我认为他的问题内容是正确的,伊迪特