필터 지우기
필터 지우기

problem with repeating index values

조회 수: 2 (최근 30일)
Pinpress
Pinpress 2012년 8월 15일
Hi,
Suppose a = [0 0 0 0]; if I do:
a([1 1 2 2 2])= a([1 1 2 2 2])+ 1;
I get: [1 1 0 0];
However, what I really want is:
[2 3 0 0];
What would be the easiest way do achieve this?

답변 (5개)

Tom
Tom 2012년 8월 15일
I'm not 100% sure what you're trying to do, but is this what you're after?
a = [0 0 0 0];
Index=[1 1 2 2 2];
for n=1:numel(Index)
a(Index(n))=a(Index(n))+1;
end
  댓글 수: 2
Matt Fig
Matt Fig 2012년 8월 15일
Pinpress comments,
Thanks -- yes that's what I was trying to do. However, it has a potentially very slow "for" loop for a large dataset, which isn't what I am looking for.
Image Analyst
Image Analyst 2012년 8월 16일
Wow. How many elements do you have? I ran through 10 million iterations of Tom's for loop in a fraction of a second. So having a for loop doesn't seem to add much overhead. Do you have more than, say, a billion iterations to do?

댓글을 달려면 로그인하십시오.


Tom
Tom 2012년 8월 15일
편집: Tom 2012년 8월 15일
This avoids using a loop, but it might be more limited than what you require. I extended the indexing array so you can a bit more about what happens (the bsxfun finds all values in the index that equal each unique value of the index, and this is summed to get the amount each one occurs)
a = [0 0 0 0];
Index=[2 2 3 3 3];
U=unique(Index);
a(U)=sum(bsxfun(@eq,Index,U'),2)
(Apologies if every time you read this I've edited it)

Star Strider
Star Strider 2012년 8월 15일
편집: Star Strider 2012년 8월 17일
This is my solution:
a = [0 0 0 0];
idx = [1 1 2 2 2]'
A = accumarray(idx, ones(size(idx))) EDIT -> A = accumarray(idx, 1)
uidx = unique(idx)
a(uidx) = A'
Likely not as efficient a solution as you would like, but it sort of gets you there.
  댓글 수: 2
Walter Roberson
Walter Roberson 2012년 8월 16일
You can use A = accumarray(idx, 1) instead of constructing the ones() array.
Caution: if the unique indices were 1 and 3, then A would have indices 1, 2, 3, with the 2 position being a zero. You would not assign a([1 3]) to be the three values from A, because that would be a length mis-match. But you could use
a(uidx) = A(uidx);
The reason for doing that rather than a = A'; is that there might be trailing positions in "a" that were not touched by the indices.
Mind you, another way of dealing with that situation would be:
a = [0 0 0 0];
idx = [1 1 2 2 2]'
a = accumarray(idx, 1, [max(idx) 1]) .';
Star Strider
Star Strider 2012년 8월 16일
편집: Star Strider 2012년 8월 16일
I discovered later, after I remembered that accumarray demands a column vector rather than the initial row vector (that it did not like) for the first argument, that it doesn't have any strong opinions about the second. I initially misinterpreted its error message and thought it wanted vectors of the same length for both arguments. (The ones vector needs to be replaced by ‘1’ for esthetics if not efficiency, but I didn't edit my code because then your comment wouldn't have a context.)
As I understand the question and the preferred outcome, there are trailing positions in a that aren't touched by the indices. That's the reason I wrote it as I did, i.e.:
However, what I really want is:
[2 3 0 0];
Maybe I missed something.
Anyway, with Bruno Luong not here, I wanted to be sure accumuarray got a mention!

댓글을 달려면 로그인하십시오.


Matt Fig
Matt Fig 2012년 8월 16일
편집: Matt Fig 2012년 8월 16일
If you have:
idx = [1 1 2 2 2];
a = [0 0 0 0]; % Or any row vector, for generality.
why not just do:
a = a + histc(idx,1:length(a)); % Use length to make it general
This should be extremely fast, as HISTC is built-in.

Andrei Bobrov
Andrei Bobrov 2012년 8월 16일
a = [0 0 0 0];
Index=[1 1 2 2 2];
s = regionprops(Index,'Area');
a(unique(Index)) = [s.Area];

카테고리

Help CenterFile Exchange에서 Matrix Indexing에 대해 자세히 알아보기

태그

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!

Translated by