【问题标题】:MATLAB - Find repeated values in a column and extract values from that rowMATLAB - 在列中查找重复值并从该行中提取值
【发布时间】:2015-08-15 15:58:28
【问题描述】:

我在第一列有一个重复值的矩阵,例如:

A = [
1  34  463;
2  45  684;
2  23  352;
3  31  256;
1  46  742;
4  25  234]

使用A,我希望从第二列中为第一列中的每个值提取数据以输出B。如果第 1 列中的值发生重复,则第 2 列中的相应值被放入一个额外的输出列中(在没有重复发生的情况下可以使用 NaN)。例如:

B = [
1  34  46;
2  45  23;
3  31  NaN;
4  25  NaN]

B 中的第 1 列不是必需的,但在此处包含以进行说明)

我尝试使用 find 函数、if 语句和循环的组合,但没有成功。理想情况下,成功的方法也会很有效,因为实际数据集很大。

我使用版本 R2012a。请指教。

【问题讨论】:

    标签: matlab matrix


    【解决方案1】:

    您可以使用cell-arrays 来解决这类问题。当所有列或所有行的长度不相等时,使用元胞数组。每行/列可以有不同的大小。它们不需要填充来使它们的大小都相等。

    一种使用accumarray的方法

    [~,~,idx] = unique(A(:,1));
    outC = accumarray(idx,A(:,2),[],@(x) {x.'})    %//'
    %// If you want the outputs in sorted order use the following code instead
    %// outC = accumarray(idx,A(:,2),[],@(x) {sort(x).'})
    
    outC = 
    
    [1x2 double]
    [1x2 double]
    [        31]
    [        25]
    

    您可以使用outC{1} 之类的语法访问每个单元格

    >> outC{1}
    
    ans =
    
    46    34
    

    如果你想一次查看整个矩阵,你可以使用celldisp函数

    >> celldisp(outC)
    
    outC{1} =
    46    34
    
    outC{2} =
    23    45
    
    outC{3} =
    31
    
    outC{4} =
    25
    

    如果您想将输出作为NaN 填充矩阵而不是单元格数组,您可以执行以下操作(在您获得上面的outC 之后):

    使用bsxfuncellfun 的方法

    lens = cellfun(@numel,outC);
    maxSize = max(lens);
    out = nan(maxSize,numel(outC));
    mask = bsxfun(@le,(1:maxSize).',lens(:).')
    out(mask) = horzcat(outC{:});
    out = out.'
    

    输出:

    out =
    
    46    34
    23    45
    31   NaN
    25   NaN
    

    如果您使用替代方法(输出排序)找到outC,结果将是:

    out =
    
    34    46
    23    45
    31   NaN
    25   NaN
    

    【讨论】:

    • 谢谢。但是,当我在我的实际数据集上进行测试时,我收到以下错误:Error using accumarray. First input SUBS must contain positive integer subscripts. 除了大小之外,唯一显着的区别是实际的第一列以零开头 - 这可能是错误的根源吗?
    • 第一列可能有零或负数,所以可以使用unique 来获取唯一ID。
    • @Divakar,肯定会编辑。猜猜你已经这样做了。 ;)
    【解决方案2】:

    这是一种方法 -

    [~,~,idx] = unique(A(:,1),'stable') %// Find IDs for each element from col-1
    [~,sorted_idx] = sort(idx)  %// Get sorted IDs
    grp_vals = A(sorted_idx,2)  %// Get second column elements grouped together
    grp_lens = accumarray(idx,1)%// Find Group lengths
    
    %// Create a mask for a 2D array where the ones are places where grouped 
    %// elements are to be put.
    mask = bsxfun(@le,[1:max(grp_lens)]',grp_lens(:).') 
    
    %// Create a nan filled array of same shape as mask and finally fill masked 
    %// places with grouped elements. Transpose at the end to get desired output.
    out = nan(size(mask))
    out(mask) = grp_vals
    out = out.'
    

    示例运行 -

    >> A,out
    A =
         1    34   463
         2    45   684
         0    23   352
        -3    31   256
         1    46   742
         4    25   234
         1    12    99
        -3   -20    56
    out =
        34    46    12
        45   NaN   NaN
        23   NaN   NaN
        31   -20   NaN
        25   NaN   NaN
    

    【讨论】:

    • 谢谢。虽然它在此示例中有效,但在应用于我的数据集时排序是一个问题。输出值与正确的行不对应。
    猜你喜欢
    • 1970-01-01
    • 2021-06-29
    • 1970-01-01
    • 1970-01-01
    • 2021-08-07
    • 1970-01-01
    • 2014-10-22
    • 2020-02-12
    • 1970-01-01
    相关资源
    最近更新 更多