Reputation: 1219
I don't know how to phrase this, but an example:
x = [1 4 4 5 5 5];
y = [5 1 3 3 4 5];
and then I'd like output
xs = [1 4 5];
ys = [5 2 4];
frequencies = [1 2 3]
(because the average 'y' at x=1 is 5
, and the average 'y' at x=4 is (1+3)/2 = 2
, and the average 'y' at x=5 is (3+4+5)/3 = 4
).
I can compute this in a clumsy way but maybe there's a nice solution.
Upvotes: 3
Views: 1958
Reputation: 1395
x = [1 4 4 5 5 5];
y = [5 1 3 3 4 5];
xs = unique(x);
[frequencies,bin] = histc(x,xs);
ys = arrayfun(@(i) mean(y(bin==i)), 1:length(xs));
Upvotes: 3
Reputation: 784
@ioum 's answer worked great for me, there was a small mistake though in the last line, that came up when I gave as an input other vectors than the ones posted here. For example, after deleting the last element of each vector the answer should be:
ys = [5 2 3.5]
The slightly corrected code is:
x = [1 4 4 5 5 5];
y = [5 1 3 3 4 5];
xs = unique(x);
[frequencies,bin] = histc(x,xs);
ys = arrayfun(@(i) mean(y(bin==i)), 1:length(xs));
I tried to edit @ioum 's post, but the edit did not go through.
Upvotes: 2
Reputation: 21561
Though I would recommend one of the histogram approaches, here is how I would do it in a loop. Not that much different from some other solutions but I believe it is just a little nicer so I will post it anyway.
xs = unique(x)
for t = 1:length(xs)
idx = x == xs(t);
ys(t) = mean(y(idx));
frequencies(t) = sum(idx);
end
Upvotes: 0
Reputation: 89
here is my code, hope it helps...
x=sort(x);
ind=1;
for i=1:length(x)
if (i>1 && x(i)==x(i-1))
continue;
end
xs(ind)=x(i);
freq(ind)=sum((x==x(i)));
ys(ind)=sum((x==x(i)).*y)/freq(ind);
ind=ind+1;
end
Upvotes: 0
Reputation: 46445
You can use the histogramming function histc
to get each of the categories:
x = [ 1 4 4 5 5 5];
y = [ 5 1 3 3 4 5];
xs = unique(x);
[frequencies xb] = histc(x, xs); % counts the number of each unique occurrence
ysp = sparse(1:numel(x), xb, y); % a sparse matrix is a good way to organize the numbers
ys = full(sum(ysp)./sum(ysp>0)); % each column in the matrix corresponds to a "index"
This gives you the three arrays you wanted. I think this is quite clean and efficient - no looping, only four lines of code.
Upvotes: 4
Reputation: 25
x = [1 4 4 5 5 5]';
y = [5 1 3 3 4 5]';
%this can probably be done smarter...
indexlong=accumarray(x,x,[],@mean)'
meanlong=accumarray(x,y,[],@mean)'
frequencieslong=accumarray(x,1)'
%leave out zeros
takethese=(indexlong>0);
xs=indexlong(takethese)
ys=meanlong(takethese)
frequencies=frequencieslong(takethese)
Upvotes: 0
Reputation: 3994
I'm not sure if this solution would be considered elegant enough, but this should work:
x = [1 4 4 5 5 5];
y = [5 1 3 3 4 5];
[xs,I,J] = unique(x); %The value of the index vector I is not required here.
ys = zeros(size(xs));
frequencies = zeros(size(xs));
for i = 1:max(J)
I = find(J==i);
ys(i) = mean(y(I));
frequencies(i) = length(I);
end
xs,ys,frequencies
The output would be:
xs =
1 4 5
ys =
5 2 4
frequencies =
1 2 3
I hope this helps.
Upvotes: 0