Matlab 合并不同单元的元素
假设我们有一个由ID和一个属性组成的单元格数组,例如Matlab 合并不同单元的元素,matlab,cell,Matlab,Cell,假设我们有一个由ID和一个属性组成的单元格数组,例如 A{1,1}=[1 2;2 4] A{1,2}=[2 3 5;8 5 6] 现在,我想有一个最终输出,由两个单元格的唯一ID(第一行值)组成,相应的列分别具有每个单元格的属性值。 i、 e 似乎不可能使用像C=[unique(A{1,:}(1,:)')]这样的东西。非常感谢您的帮助。假设每个单元格有两行和数量可变的列,其中第一行是ID,第二行是属性,我会将所有单元格合并到一个二维矩阵中并使用accumarray在这里非常合适,因为您希望将
A{1,1}=[1 2;2 4]
A{1,2}=[2 3 5;8 5 6]
现在,我想有一个最终输出,由两个单元格的唯一ID(第一行值)组成,相应的列分别具有每个单元格的属性值。
i、 e
似乎不可能使用像
C=[unique(A{1,:}(1,:)')]
这样的东西。非常感谢您的帮助。假设每个单元格有两行和数量可变的列,其中第一行是ID,第二行是属性,我会将所有单元格合并到一个二维矩阵中并使用accumarray
在这里非常合适,因为您希望将属于同一ID的值分组在一起,并对其应用函数。在我们的例子中,我们的函数只需将值放在一个单元格数组中,我们将确保对值进行排序,因为按accumarray
每个ID分组的值以随机顺序进入函数
用于将单元格转换为2D矩阵,对其进行转置,使其与accumarray兼容,然后使用它。我需要注意的一点是,如果缺少任何ID,accumarray
将使此插槽变空。我所说的缺失是指在您的示例中,ID 4缺失,因为3和5之间存在差距,ID 6也在5和7之间(我在您给我的评论中添加了该示例)。由于数据中的最大ID为7,accumarray
通过以1为增量分配从ID 1到ID 7的输出来工作。我们需要解决的最后一件事是从accumarray
的输出中消除任何空单元格,以完成分组
顺便说一句,我将假设您的单元格数组由一行单元格组成,就像您的示例一样。。。。因此:
%// Setup
A{1,1}=[1 2;2 4];
A{1,2}=[2 3 5;8 5 6];
A{1,3}=[7;8];
%// Convert row of cell arrays to a single 2D matrix, then transpose for accumarray
B = cell2mat(A).';
%// Group IDs together and ensure they're sorted
out = accumarray(B(:,1), B(:,2), [], @(x) {sort(x)});
%// Add a column of IDs and concatenate with the previous output
IDs = num2cell((1:numel(out)).');
out = [IDs out];
%// Any cells from the grouping that are empty, eliminate
ind = cellfun(@isempty, out(:,2));
out(ind,:) = [];
我们得到:
out =
[1] [ 2]
[2] [2x1 double]
[3] [ 5]
[5] [ 6]
[7] [ 8]
>> celldisp(out(2,:))
ans{1} =
2
ans{2} =
4
8
>> out{1}
ans =
[1] [ 2]
[2] [2x1 double]
[3] [ 5]
[5] [ 6]
[7] [ 8]
>> out{2}
ans =
[1] [2x1 double]
[2] [ 4]
>> celldisp(out{1}(2,:))
ans{1} =
2
ans{2} =
4
8
>> celldisp(out{2}(1,:))
ans{1} =
1
ans{2} =
2
7
如果您希望在2D单元数组上执行此操作,其中此单元数组的每一行表示同一问题的单独实例,我的一个建议是可能在每一行上循环。类似于此,在评论中给出了您的示例:
%// Setup
A{1,1}=[1 2;2 4];
A{1,2}=[2 3 5;8 5 6];
A{1,3}=[7;8];
A{2,1}=[1 2;2 4];
A{2,2}=[1;7];
%// Make a cell array that will contain the output per row
out = cell(size(A,1),1);
for idx = 1 : size(A,1)
%// Convert row of cell arrays to a single 2D matrix, then transpose for accumarray
B = cell2mat(A(idx,:)).';
%// Group IDs together and ensure they're sorted
out{idx} = accumarray(B(:,1), B(:,2), [], @(x) {sort(x)});
%// Add a column of IDs and concatenate with the previous output
IDs = num2cell((1:numel(out{idx})).');
out{idx} = [IDs out{idx}];
%// Any cells from the grouping that are empty, eliminate
ind = cellfun(@isempty, out{idx}(:,2));
out{idx}(ind,:) = [];
end
我们得到:
out =
[1] [ 2]
[2] [2x1 double]
[3] [ 5]
[5] [ 6]
[7] [ 8]
>> celldisp(out(2,:))
ans{1} =
2
ans{2} =
4
8
>> out{1}
ans =
[1] [ 2]
[2] [2x1 double]
[3] [ 5]
[5] [ 6]
[7] [ 8]
>> out{2}
ans =
[1] [2x1 double]
[2] [ 4]
>> celldisp(out{1}(2,:))
ans{1} =
2
ans{2} =
4
8
>> celldisp(out{2}(1,:))
ans{1} =
1
ans{2} =
2
7
非常感谢,我想强调一点,我的单元格是单行,但列数可变,例如
a{1,3}=[7;8]
,而且我也希望在最终输出的第一列中有ID(使用类似unique
)。因此,我能够知道哪个输出对应哪个id。您的解决方案会被更改以包含这些更改吗?@hamideh-尝试执行cell2mat(A(I,:)。
。您使用的是{}
而不是()
,后者将返回逗号分隔的列表。这就是为什么会出现输入参数过多的错误。在每一行上独立循环应该是可行的,但是要确保你正确地切片到你的单元格数组中!我得到了想要的答案!你为我节省了很多时间和精力。再次感谢:)@hamideh-顺便说一句,如果您需要更多帮助,请随时访问我们的MATLAB聊天室:-祝您好运!使用您的提示,我发现这样的解决方案集成在解决方案的第一个for循环中:for idxx=1:size(out{idx},1)out_final{idx}(idxx,1)=IDs(idxx);out_final{idx}(idxx,2)=num2单元(max(cell2mat(out{idx}(idxx,2:end)));结束
以便我们可以找到每个项目的最大值。再次感谢:)