【问题标题】:MATLAB: Keeping a number of random rows in a matrix which satisfy certain conditionsMATLAB:在满足某些条件的矩阵中保留许多随机行
【发布时间】:2013-04-03 23:53:02
【问题描述】:

我在 Matlab 中有一个与此类似的矩阵,除了有数千行:

A =

     5     6     7     8
     6     1     2     3
     5     1     4     8
     5     2     3     7
     5     8     7     2
     6     1     3     8
     5     2     1     6
     6     3     2     1

我想得到一个矩阵,该矩阵具有三个随机行,第一列为“5”,三个随机行,第一列为“6”。所以在这种情况下,输出矩阵看起来像这样:

A =

     5     6     7     8
     6     1     2     3
     5     2     3     7
     6     1     3     8
     5     2     1     6
     6     3     2     1

行必须是随机的,而不仅仅是原始矩阵中的前三个或后三个。 我不太确定如何开始,所以任何帮助将不胜感激。

编辑:这是我迄今为止最成功的尝试。我在第一列中找到了所有带有“5”的行:

BLocation = find(A(:,1) == 5);
B = A(BLocation,:);

然后我尝试像这样使用“randsample”从 B 中找到三个随机行:

C = randsample(B,3);

但 'randsample' 不适用于矩阵。

我也认为这可以更有效地完成。

【问题讨论】:

    标签: matlab matrix random-sample


    【解决方案1】:

    您需要在满足条件的行索引上运行randsample,即等于 5 或​​ 6。

    n = size(A,1);
    
    % construct the linear indices for rows with 5 and 6 
    indexA = 1:n; 
    index5 = indexA(A(:,1)==5);
    index6 = indexA(A(:,1)==6);
    
    % sample three (randomly) from each 
    nSamples = 3;
    r5 = randsample(index5, nSamples);
    r6 = randsample(index6, nSamples);
    
    % new matrix from concatenation 
    B = [A(r5,:); A(r6,:)];
    

    更新:您也可以使用find 替换原来的索引结构,正如 yuk 建议的那样,这被证明更快(并且优化了!)。

    Bechmark(MATLAB R2012a)

    A = randi(10, 1e8, 2); % 10^8 rows random matrix of 1-10
    
    tic;
    n = size(A,1);
    indexA = 1:n;
    index5_1 = indexA(A(:,1)==5);
    toc
    
    tic;
    index5_2 = find(A(:,1)==5);
    toc
    
    Elapsed time is 1.234857 seconds.
    Elapsed time is 0.679076 seconds.
    

    【讨论】:

    • @yuk 如果你得到相同的输出,为什么你会有调用 find 的开销,因为你可以直接索引 1:n,即行索引的向量?通过以上,您仅在向量 1:n 上使用逻辑索引,您可以分析地构造该向量。除非find 正在做一些额外的性能优化,否则我假设它对于更大的矩阵会更慢。不过,它不需要在内存中分配新的向量。
    • @gevang 我检查了你的代码的速度。对于较大的矩阵,它不会减慢很多。我的代码(下面的答案)对于小矩阵(大约 10000 行)更快,但之后它的执行时间开始增加。我认为那是因为我在连接。
    • @gevang,我测试了您的代码与 find 在百万行矩阵上的时序(仅索引构造),并且 find 大约快两倍。即使indexA 创建不计算在内,它也会更快。可能是因为发现优化。
    • @yuk 太棒了!你说的对。我不知道,也不会检查。我认为默认情况下 find 有开销。使用小基准进行更新。
    • @Parag 因为@yuk 还指出randsample() 调用randperm()。您可以随时排除对randperm 的相关调用。无论如何,我使用 OP 提到的randsample 给了你一个替代答案。
    【解决方案2】:

    你可以这样做:

    desiredMat=[];
    mat1=A(A(:,1)==5,:);
    mat1=mat1(randperm(size(mat1,1)),:);
    desiredMat=[desiredMat;mat1(1:3,:)];
    mat1=A(A(:,1)==6,:);
    mat1=mat1(randperm(size(mat1,1)),:);
    desiredMat=[desiredMat;mat1(1:3,:)];
    

    上面的代码使用了逻辑索引。您也可以使用find 函数来执行此操作(逻辑索引总是比find 快)。

    【讨论】:

    • 是的,这段代码比@gevand 快两倍多。首先randperm 是内置函数。 randsample 实际上调用了randperm。其次可能是由于直接索引。我只建议不要增长desireMat。最好创建mat2 并将它们与desiredMat=[mat1(1:3,:); mat2(1:3,:)]; 连接起来。快一点。
    猜你喜欢
    • 2021-03-01
    • 2020-04-20
    • 2016-09-10
    • 1970-01-01
    • 1970-01-01
    • 2011-07-20
    • 1970-01-01
    • 2023-03-16
    相关资源
    最近更新 更多