Matlab 在每列矩阵中查找最后两个非唯一观测值
我有一个矩阵a,我想找到每列的最后两个非NaN值 例如,生成以下矩阵: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, 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值。我认为他的问题内容是正确的,伊迪特