Replacing duplicates in a vector of required length
3 次查看(过去 30 天)
显示 更早的评论
Hi there, I am simulating events of different durations and am stuck about how to replace duplicate values in my vector. This is what I have so far:
To create 14 events that occur for a range of 120 to 300 seconds (the total number seconds of all 14 events must add up to 2880 seconds).
du=round(randfixedsum(14,1,2880,120,300))
To generate start times for each event:
st=randperm(28800,14)
duration = du’
m = cumsum(duration);
t = m - duration + 1; s = zeros(1,m(end));
s(t) = 1;
ii = cumsum(s);
out = (1:m(end)) - t(ii) + st(ii);
sort(out)'
out=unique(out)
I end up with a list of seconds during which these events are occurring, but the total seconds now falls short of the required (2880s) as I have removed the duplicates. How do I replace these duplicates so that all the requirements are met (i.e., all the variables in this - du=round(randfixedsum(14,1,2880,120,300)).
I hope this makes sencec, any help is greatly appreciated!
0 个评论
采纳的回答
Roger Stafford
2013-8-26
If you are not concerned with duplicates in 'du', here is a method which only calls on 'randfixedsum' once, but adjusts an offset so as to obtain the desired sum when rounded to integers:
x = randfixedsum(14,1,2880,120,300);
tp = .5; tm = -.5;
for k = 1:53
t0 = (tp+tm)/2;
du = round(x+t0); % Round with offset
e = sum(du)-2880;
if e > 0, tp = t0;
elseif e < 0, tm = t0;
else break % Break out when sum is correct
end
end
The same would apply to the calculation I recommended for the intervals between "events" for which you might presumably call on 'randfixedsum' with:
x = randfixedsum(15,1,25920,0,25920);
(or perhaps you have some other constraint to place on these intervals between "events" tnan merely lying between 0 and 25920.)
更多回答(1 个)
Roger Stafford
2013-8-26
I ran your computation
du=round(randfixedsum(14,1,2880,120,300));
several thousand times and found that the odds of getting a sum of exactly 2880 without any duplications are about one in four, which are not bad odds. I would suggest you use a while-loop to repeat this calculation until it succeeds, which on the average would require about four repetitions.
b = true;
while b
du=round(randfixedsum(14,1,2880,120,300));
b = sum(du)~=2880 | any(diff(sort(du))==0);
end
(Of course if those numbers: 120, 300, 14, and 2880, are altered, that would change the probability of success.)
2 个评论
Roger Stafford
2013-8-26
The details of what you are trying to achieve are still unclear, but I have the impression that you want something like this. You have 14 events, each of which must last an integral number of seconds, and their total time should be 2880 seconds. These events should be placed in a larger interval of time lasting 28800 seconds with random starting times but such that the event intervals don't overlap. Is that roughly what you are after?
There is no need to randomize the ordering of the event times, since that is already done by 'randfixedsum'. What I think you need is a second application of 'randfixedsum' for the 15 intervals between events, before the first one, or after the last one, accompanied also by a 'round' operation for which the sum is exactly 28800-2880 (or something like that anyway.) From this you can generate all starting times. You are getting into trouble trying to use 'randperm' to generate those starting times.
另请参阅
类别
在 Help Center 和 File Exchange 中查找有关 Creating and Concatenating Matrices 的更多信息
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!