MATLAB向量:防止来自相同范围的连续值

时间:2012-07-03 15:00:55

标签: matlab random vector duplicates

好吧,这可能看起来像一个奇怪的问题,但请耐心等待。

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

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

“完成”只是我们从中获取样本的值的范围,所以不要担心。正如您所看到的,这些样本来自一系列值,然后使用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),请确保来自相同范围的“连续”值不相同。 / p> 那么,那就是我想做的事情。这绝不是最好的方法,所以任何建议/替代方案当然都是值得赞赏的。我知道我可以使用多个向量更好地做到这一点,但由于各种原因,我需要将它作为单个长向量(我的脚本设计的方式如果我为每个值范围都有一个单独的向量,它将无法工作) 。

4 个答案:

答案 0 :(得分:3)

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

%# 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

答案 1 :(得分: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

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

答案 2 :(得分:1)

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

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

答案 3 :(得分:1)

这是一种与其他人一直折腾的方法不同的方法。我在这里工作的前提是你希望在一个向量中随机排列值,而不需要重复。在我们给出输入之前,我不确定您正在应用的其他约束。

我的想法是使用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享受!