在MATLAB中使用unique()重构向量
假设在MATLAB中使用unique()重构向量,matlab,unique,sorting,Matlab,Unique,Sorting,假设A是一个200项单元格数组,包含4个不同的字符串(每个字符串有50个重复)。 B是包含一些整数的200项向量 我正在使用[cellNos cellStartInd enumCells]=unique(A)并获取A中的哪个项等于唯一字符串之一(enumCells是一个包含整数1-4的数组,类似于枚举字符串) 我想使用此信息从B创建一个4x50值矩阵,以便每列都有特定唯一字符串的值。换句话说,我想将B重塑为一个矩阵,其中列根据a中的每个唯一字符串排列。如果我正确理解了您的问题,可以使用find函
A
是一个200项单元格数组,包含4个不同的字符串(每个字符串有50个重复)。
B
是包含一些整数的200项向量
我正在使用[cellNos cellStartInd enumCells]=unique(A)
并获取A
中的哪个项等于唯一字符串之一(enumCells是一个包含整数1-4的数组,类似于枚举字符串)
我想使用此信息从
B
创建一个4x50值矩阵,以便每列都有特定唯一字符串的值。换句话说,我想将B
重塑为一个矩阵,其中列根据a
中的每个唯一字符串排列。如果我正确理解了您的问题,可以使用find函数完成此操作。
要创建矩阵,只需编写:
M(:,1) = B(find(enumCells==1));
M(:,2) = B(find(enumCells==2));
M(:,3) = B(find(enumCells==3));
M(:,4) = B(find(enumCells==4));
也许有一种更优雅的方法,但这应该行得通
编辑:您可以尝试使用“排序”来完成。排序函数可以将排序的排列作为输出。尝试:
[s perm] = sort(enumCells);
M = reshape(B(perm),50,4);
如果每个字符串的条目数相同,如果条目数不同,此方法将起作用。请参阅@gnovice solution
NumStrings = numel(CellNos);
M = zeros(size(B,1)/NumStrings,NumStrings);
for i = 1:NumStrings
M(:,i) = B(strcmp(B,CellNos{i}));
end
此外,如果您提前知道唯一字符串是什么(即CellNos),这允许您跳过唯一调用,这相对比较昂贵。假设您已经知道将有多少次重复,并且所有字符串都以相同的频率重复,您可以执行以下操作:
%# sort to find where the entries occur (remember: sort does stable sorting)
[~,sortIdx] = sort(enumCells);
%# preassign the output to 50-by-4 for easy linear indexing
newB = zeros(50,4);
%# fill in values from B: first the 50 ones, then the 50 2's etc
newB(:) = B(sortIdx);
%# transpose to get a 4-by-50 array
newB = newB';
或者,以更紧凑的方式(谢谢@Rich C)
对于一般情况,如果您有不同的字符串,并且每个字符串出现的次数不同,
M_i
,则B
中的每个对应值集将具有不同的长度,您将无法将这些值集串联到一个数字数组中。您将不得不存储在N
-元素中设置ets,您可以使用函数和:
在每个字符串出现相同次数的特定情况下,上述代码仍然可以正常工作,您可以选择将输出从单元格数组转换为所需的数字数组,如下所示:
associatedValues = [associatedValues{:}];
注意:由于不能保证保持其累计项目的相对顺序,因此
关联值的单元格中项目的顺序可能与向量B
中项目的相对顺序不匹配。确保B
中的原始相对顺序保持不变的一种方法是修改调用修订如下:
associatedValues = accumarray(index(:),1:numel(B),[],@(x) {B(sort(x))});
或者,您可以对输入进行排序以获得相同的效果:
[index,sortIndex] = sort(index);
associatedValues = accumarray(index(:),B(sortIndex),[],@(x) {x});
谢谢,这应该适用于4个唯一的字符串。实际上,我想要的解决方案需要更少的硬编码和可伸缩性,因为实际问题不同(即更复杂)这是最好的解决方案,前提是您事先知道重复。您可以将最后3行折叠为:newB=reformate(B(sortIdx),[50 4])
@Rich C:谢谢你的建议!要折叠最后一行,你的解决方案还需要一个额外的转置,顺便说一句,+1再次很好地使用了accumarray
!在我有排序想法之前,我尝试过这个解决方案,但失败了。@Jonas:对于所有字符串出现相同次数的简单情况,你的sol这绝对是一条路要走
associatedValues = accumarray(index(:),1:numel(B),[],@(x) {B(sort(x))});
[index,sortIndex] = sort(index);
associatedValues = accumarray(index(:),B(sortIndex),[],@(x) {x});