2012-07-03 3 views
4

Хорошо, это может показаться странным вопросом, но нести меня.Вектор MATLAB: предотвращать последовательные значения из того же диапазона

Так что у меня есть случайный вектор в файле .m с определенными ограничениями, встроенными в него. Вот мой код:

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

«Done» только диапазон значений мы берем пробу из, так что не беспокойтесь об этом. Как вы можете видеть, это изменяет диапазон значений, а затем вырезает этот случайный вектор с помощью функции 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) убедитесь, что «последовательные» значения из того же диапазона не идентичны.

Итак, вот что я хочу делать. Это никоим образом не может быть лучшим способом сделать это, поэтому любые советы/альтернативы, конечно, оценены. Я знаю, что я могу сделать это лучше с несколькими векторами, но по разным причинам мне нужно, чтобы это был один длинный вектор (как мой сценарий был спроектирован, он просто не работал бы, если бы у меня был отдельный вектор для каждого диапазона значений) ,

+1

Честно говоря, это действительно похоже на странную вещь: D Почему бы не просто сгруппировать первый вектор в начале? – Juhl

+1

подождите секунду, не правда ли ['unique'] (http://www.mathworks.se/help/techdoc/ref/unique.html)? ты ищешь? – Juhl

+0

Разве вы не можете сделать отдельный вектор для каждой категории? – Dan

ответ

3

Что вы можете сделать, это создать четыре случайных вектора, по одному для каждой категории, гарантировать, что они не содержат никаких двух последовательных равных значений, а затем построить ваш окончательный случайный вектор путем упорядоченного набора значений из случайных категорий, т.е.

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

Сначала мы назначаем каждый элемент бен номер диапазона лежит в:

[~,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 

Сделайте это для всех диапазонов, и собирать те проблематична индексы. Затем решите, как вы хотите с ними справиться (удалите их, сгенерируйте другие цифры на своем месте и т. Д.)

+0

Я не думаю, что это совершенно правильно ... если мое понимание вопроса OP правильное, и вы установите randvec (15) = 7, то этот подход будет определять индекс 15 как индекс проблемы, хотя только семь происходит один раз в диапазоне 1-15. – sfstewman

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 
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 наслаждайтесь!

+0

Это позволяет избежать любых дубликатов вообще, а не только последовательных дубликатов, и я понял, что OP хочет сэмплировать с заменой. – Jonas

 Смежные вопросы

  • Нет связанных вопросов^_^