【问题标题】:MATLAB vector: prevent consecutive values from same rangeMATLAB向量:防止同一范围内的连续值
【发布时间】:2012-07-04 01:14:52
【问题描述】:

好的,这似乎是一个奇怪的问题,但请耐心等待。

所以我在 .m 文件中有一个随机向量,其中内置了某些约束。这是我的代码:

 randvecall = randsample(done, done, true);
 randvec = randvecall([1;diff(randvecall(:))]~=0);

“完成”只是我们从中提取样本的值的范围,所以不用担心。如您所见,此 randsamples 从一系列值中进行采样,然后使用 diff 函数修剪此随机向量,从而删除连续的重复值。向量中仍有可能出现重复值,但它们根本不可能是连续的。

这一切都很好,并且工作得很好。

比如说,randvec 看起来像这样:

randvec =

    54
    47
    52
    26
    39
     2
    14
    51
    24
     6
    19
    56
    34
    46
    12
     7
    41
    18
    29
     7

实际上要长得多,大约有 60-70 个值,但你明白了。

我想要做的是在这个向量上添加一点额外的约束。当我从这个向量中采样时,这些值会根据它们的范围进行分类。所以 1-15 的值是第 1 类,16-30 是第 2 类,依此类推。造成这种情况的原因并不重要,但它是程序中非常重要的一部分。因此,如果您查看我在上面提供的值,您会看到这样的部分:

     7
    41
    18
    29
     7

这实际上对我的程序不利。因为值范围是分开处理的,所以 41、18 和 29 的使用与 7 不同。因此,出于所有意图和目的,7 连续出现在我的脚本中。我想要做的是在生成向量时以某种方式解析/修改/无论向量,以便某个范围内的相同数字不能“连续”出现两次,无论它们之间有多少来自不同范围的其他数字。这有意义吗/我描述得好吗?所以,我希望 MATLAB 搜索向量,并且对于特定范围内的所有值(1-15、16-30、31-45、46-60),确保同一范围内的“连续”值不相同。

那么,这就是我想要做的。这可能无论如何都不是最好的方法,所以当然,任何建议/替代方案都值得赞赏。我知道我可以用多个向量做得更好,但是由于各种原因,我需要它是一个单一的长向量(我的脚本的设计方式如果我为每个值范围都有一个单独的向量,它就行不通) .

【问题讨论】:

  • 老实说,这似乎是一件很奇怪的事情:D 为什么不在一开始就对第一个向量进行分组?
  • 等一下,不就是unique吗?你在找吗?
  • 你不能为每个类别制作一个单独的向量吗?
  • 您可以使用模数数学将它们合并到您要查找的范围中,然后如果您愿意,并且如果我遵循您想要的,则应用唯一命令。
  • 我不想使用唯一的,因为我仍然想要重复的值,而不是连续的值。所以,如果 A = [9 28 40 9 55 38 6 9],unique 会给我 [6 9 28 38 40 55]。我想要 [9 28 40 55 38 6 9]。我只想从同一范围内删除连续的重复项。上面的第二个 9 不会被删除,因为 6 和它在同一个范围内,所以它不是连续的重复。是的,我意识到这是一件奇怪的事情。老实说,这并不重要,这更像是一时兴起,呵呵。

标签: matlab random vector duplicates


【解决方案1】:

您可能想要做的是创建四个随机向量,每个类别一个,确保它们不包含任何两个连续相等的值,然后通过从随机类别中有序选取值来构建最终的随机向量,即

%# make a 50-by-nCategories array of random numbers
categories = [1,16,31,46;15,30,45,60]; %# category min/max
nCategories = size(categories,2);
randomCategories = zeros(50,nCategories);

for c=1:nCategories
   %# draw 100 numbers for good measure
   tmp = randi(categories(:,c),[100 1]);
   tmp(diff(tmp==0)) = []; %# remove consecutive duplicates

   %# store
   randomCategories(:,c) = tmp(1:50);
end

%# select from which bins to pick. Use half the numbers, so that we don't force the 
%# numbers of entries per category to be exactly equal

bins = randi(nCategories,[100,1]);

%# combine the output, i.e. replace e.g. the numbers
%# '3' in 'bins' with the consecutive entries
%# from the third category
out = zeros(100,1);
for c = 1:nCategories
   cIdx = find(bins==c);
   out(cIdx) = randomCategories(1:length(cIdx),c);
end

【讨论】:

    【解决方案2】:

    首先,我们为每个元素分配其所在范围的 bin 编号:

    [~,bins] = histc(randvec, [1 16 31 46 61]);
    

    接下来我们对每个范围进行循环,并在这些类别中查找元素。例如对于 1-16 的第一个范围,我们得到:

    >> ind = find(bins==1);       %# bin#1 of 1-16
    >> x = randvec(ind)
    ans =
         2
        14
         6
        12
         7
         7
    

    现在您可以应用相同的过程来删除连续重复项:

    >> idx = ([1;diff(x)] == 0)
    idx =
         0
         0
         0
         0
         0
         1
    >> problematicIndices = ind(idx)   %# indices into the vector: randvec
    

    对所有范围执行此操作,并收集那些有问题的索引。接下来决定如何处理它们(删除它们,在它们的位置生成其他数字,等等......)

    【讨论】:

    • 我认为这不太对...如果我对 OP 问题的理解是正确的,并且您设置了 randvec(15) = 7,那么这种方法会将索引 15 识别为问题索引,即使 7 在 1-15 范围内只出现一次。
    【解决方案3】:

    如果我正确理解您的问题,我认为这是一种解决方案。它使用唯一的,但将其应用于向量的每个子范围。在索引范围内重复的值被识别出来,以便您处理它们。

    cat_inds = [1,16,31,46,60];  % need to include last element
    for i=2:numel(cat_inds)
      randvec_part = randvec( cat_inds(i-1):cat_inds(i) );
      % Find the indices for the first unique elements in this part of the array
      [~,uniqInds] = unique(randvec_part,'first');
    
      % this binary vector identifies the indices that are duplicated in
      % this part of randvec
      %
      % NB: they are indices into randvec_part
      %
      inds_of_duplicates = ~ismember(1:numel(randvec_part), uniqInds);
    
      % code to deal with the problem indices goes here.  Modify randvec_part accordingly...
    
      % Write it back to the original vector (assumes that the length is the same)
      randvec( cat_inds(i-1):cat_inds(i) ) = randvec_part;
    end
    

    【讨论】:

      【解决方案4】:

      这是一种不同于其他人一直在折腾的方法。我在这里工作的前提是您希望在向量中随机排列值而不重复。我不确定在我们提供输入之前您还应用了哪些其他限制。

      我的想法是使用randperm 函数。

      下面是一些示例代码如何工作:

      %randvec is your vector of random values
      randvec2 = unique(randvec); % This will return the sorted list of values from randvec.
      randomizedvector = randvec2(randperm(length(randvec2)); 
      % Note: if randvec is multidimensional you'll have to use numel instead of length
      

      此时randomizedvector 应包含初始randvec 中的所有唯一值,但在唯一函数调用后“随机化”或重新随机化。现在,您可以对 randvec 进行不同的播种,以避免需要唯一的函数调用,因为只需调用 randperm(n) 将返回一个值从 1 到 n 的随机向量。

      那里只需 2 美分 =P 享受!

      【讨论】:

      • 这具有完全避免任何重复的效果,而不仅仅是连续重复,而且我知道 OP 想要通过替换进行采样。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2017-05-21
      • 1970-01-01
      • 2015-11-22
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-11-21
      相关资源
      最近更新 更多