Matlab 如何删除双数组中的重复行,以便没有一行与其前一行相同
我有4个n×1的列向量,其中共享相同的索引号意味着它们具有相同的时间戳。我想删除与前面的“行”相同的“行”,并设想递归地执行此操作,直到没有更改为止 例如,假设这4个向量是Matlab 如何删除双数组中的重复行,以便没有一行与其前一行相同,matlab,Matlab,我有4个n×1的列向量,其中共享相同的索引号意味着它们具有相同的时间戳。我想删除与前面的“行”相同的“行”,并设想递归地执行此操作,直到没有更改为止 例如,假设这4个向量是 C1=[1;1;3;3;1;1]; C2=[2;2;4;4;2;2]; C3=[0;0;0;0;0;0]; C4=[5;5;6;6;5;5]; 所需输出为 ans=[1;3;5]; 因为[C1(ans)、C2(ans)、C3(ans)、C4(ans)]是一个数组,没有与其前一行相同的行。在上述示例中,生成的向量如下所示:
C1=[1;1;3;3;1;1];
C2=[2;2;4;4;2;2];
C3=[0;0;0;0;0;0];
C4=[5;5;6;6;5;5];
所需输出为
ans=[1;3;5];
因为[C1(ans)、C2(ans)、C3(ans)、C4(ans)]
是一个数组,没有与其前一行相同的行。在上述示例中,生成的向量如下所示:
C1=[1;3;1];
C2=[2;4;2];
C3=[0;0;0];
C4=[5;6;5];
“行”是指当查看与[C1、C2、C3、C4]
按列连接的向量时的行
问题是:
- 我知道如何做它与循环。如何使用本机Matlab函数实现这一点
一些注释: 我从4个分离的列向量开始的原因如下:
关于业绩的说明 由于随机数据不合适,过于具体的数据也不合适,所以在这一点上演示性能差异有点困难。(我所说的“难”是指很难快速完成。) 但是,如果有人感兴趣的话,
timeit()
的结果如下:表中有约164k行,但只有约1k行是“唯一”行(“”)
- Cris'
方法:0.0028sdiff或
- Wolfie的
独特
方法:0.0142s
- Wolfie's
方法:0.3912sarrayfun
- Thomas's
方法:0.0057sdiff*ones
- Thomas的递归方法:无法完成。这在
下执行一分钟后,将Matlab的RAM请求放大到~70GB,并导致Win 10机器上的UI冻结,尽管该机器有大量未使用的CPUtimeit()
- 循环(但在列数上使用
):3.6313svarargin
function varargout = accum(varargin)
for i=1:numel(varargin)
varargout{i}=varargin{i}(1); % assuming single column
end
for i=2:numel(varargin{1}) % assuming equal length
TF=false;
for j=1:numel(varargin)
TF=TF||varargin{j}(i)~=varargin{j}(i-1);
end
if TF
for j=1:numel(varargin)
varargout{j}=[varargout{j};varargin{j}(i)];
end
end
end
end
如果你正在写另一个答案,需要样本数据,请告诉我。否则,我将跳过粘贴它,因为这样做没有什么用处。这里有一个选项,使用逻辑值将矩阵中的行子集
C([true; abs(C(2:end,:)-C(1:end-1,:))*ones(size(C,2),1)>0],:)
给
ans =
1 2 0 5
3 4 0 6
1 2 0 5
如果您不介意使用用户函数方法,下面可能是另一个选项,
myfun
递归计算“唯一”行
以致
>> z = myfun(C)
z =
1 2 0 5
3 4 0 6
1 2 0 5
其中
C=[C1、C2、C3、C4]
我认为以下给出了所需的输出(未测试):
find([1;diff(C1)| diff(C2)| diff(C3)| diff(C4)])
diff
为非零,其中两个后续元素不同。使用逻辑OR,我们要求任何一个向量在任何一个位置都有差异。第一个元素始终是输出的一部分find
返回非零元素的索引。您可以使用与Cris给出的答案类似的方法(find(diff(…))
),但使用unique
使其更通用
设置:
C1=[1;1;3;3;1;1];
C2=[2;2;4;4;2;2];
C3=[0;0;0;0;0;0];
C4=[5;5;6;6;5;5];
C = [C1,C2,C3,C4];
[~,~,iu] = unique( C, 'rows' );
idx = find( [1; diff(iu)] );
idx = find( [1, arrayfun( @(ii) any(C(ii,:) ~= C(ii-1,:)), 2:size(C,1) )] )
方法一:
C1=[1;1;3;3;1;1];
C2=[2;2;4;4;2;2];
C3=[0;0;0;0;0;0];
C4=[5;5;6;6;5;5];
C = [C1,C2,C3,C4];
[~,~,iu] = unique( C, 'rows' );
idx = find( [1; diff(iu)] );
idx = find( [1, arrayfun( @(ii) any(C(ii,:) ~= C(ii-1,:)), 2:size(C,1) )] )
或者,您可以循环(简写为arrayfun
)查找任何元素与前一行不同的行
方法二:
C1=[1;1;3;3;1;1];
C2=[2;2;4;4;2;2];
C3=[0;0;0;0;0;0];
C4=[5;5;6;6;5;5];
C = [C1,C2,C3,C4];
[~,~,iu] = unique( C, 'rows' );
idx = find( [1; diff(iu)] );
idx = find( [1, arrayfun( @(ii) any(C(ii,:) ~= C(ii-1,:)), 2:size(C,1) )] )
谢谢你的回答。但是
unique(u,'rows')
不应该工作,因为示例中的第一个和第三个元素可能相同,因为可能存在中间不同的“rows”。我将编辑示例以显示它。@Argyll感谢您的反馈。我通过定义一个用户函数更新了我的答案。希望它有意义代码有意义。谢谢你的解决方案。在得到更多答案后,我将在稍后发布一条注释,以重新进行基准测试。@Argyll我想如果您有许多行,那么用户函数可能会很慢。我添加了另一种应该更快的方法。只是一个问题,我想你对原始数据没有控制权?因为在这种情况下,可以将数据推送到应用程序的实时数据库(firebase、RejectionDB,…)可以大大减少所需的计算量。@obchardon:Ya我无法控制数据源。到时候,我将使用不同的供应商。但我目前的资料在某种程度上是有效的,而且价格低廉。因此,为了让一些工作顺利进行,我需要使用当前的供应商,并且在任何情况下,供应商都以独特的方式提供有价值的东西——便宜。