allocate values avoiding loop
Afficher commentaires plus anciens
I have the following matrix [t k p]
1.0000 1.0000 -1.1471
1.0000 2.0000 -1.0689
2.0000 1.0000 -0.8095
2.0000 2.0000 -2.9443
3.0000 1.0000 1.4384
3.0000 2.0000 0.3252
and I want an additional column with the mean of p for every t, hence
1.0000 1.0000 -1.1471 -1.1080
1.0000 2.0000 -1.0689 -1.1080
2.0000 1.0000 -0.8095 -1.8769
2.0000 2.0000 -2.9443 -1.8769
3.0000 1.0000 1.4384 0.8818
3.0000 2.0000 0.3252 0.8818
I can do it with the following code
if true
%Calulate the mean
A=[t p_tk];
p_t= accumarray(A(:,[1]), A(:,2), [], @nanmean, NaN);
% allocate it to long form
p_t_long= NaN(size(t));
for d = 1:max(t)
ind= t ==d;
p_t_long(ind)= p_t(d);
end
end
However, I want to avoid loops since I have a big dataset. Can anybody help?
Réponse acceptée
Plus de réponses (2)
Bruno Luong
le 8 Nov 2018
A=[...
1.0000 1.0000 -1.1471
1.0000 2.0000 -1.0689
2.0000 1.0000 -0.8095
2.0000 2.0000 -2.9443
3.0000 1.0000 1.4384
3.0000 2.0000 0.3252 ]
[~,~,J] = unique(A(:,1));
p_t= accumarray(J, A(:,3), [], @(x) mean(x,'omitnan'), NaN);
[A p_t(J)]
Result
ans =
1.0000 1.0000 -1.1471 -1.1080
1.0000 2.0000 -1.0689 -1.1080
2.0000 1.0000 -0.8095 -1.8769
2.0000 2.0000 -2.9443 -1.8769
3.0000 1.0000 1.4384 0.8818
3.0000 2.0000 0.3252 0.8818
5 commentaires
Bruno Luong
le 8 Nov 2018
Modifié(e) : Bruno Luong
le 8 Nov 2018
The old loyal ACCUMARRAY is still the king of the speed
n = 1e6;
ntest = 10;
time = zeros(2,ntest);
for i = 1:ntest
g = ceil(100*rand(n,1));
t = rand(n,1);
tic
grpAvg1 = splitapply(@mean,t,g);
time(1,i) = toc;
tic
grpAvg2 = accumarray(g,t)./accumarray(g,1);
time(2,i) = toc;
end
time = mean(time,2);
fprintf('splitapply time = %f s\n', time(1)); % splitapply time = 0.158369 s
fprintf('accumarray time = %f s\n', time(2)); % accumarray time = 0.029645 s
Rahel Braun
le 12 Nov 2018
Bruno Luong
le 12 Nov 2018
Modifié(e) : Bruno Luong
le 12 Nov 2018
Unless I misunderstood something, assignment with the mean already answered, look at the last statement
[A p_t(J)]
where p_t is accumarray output (average) and J is the third output of UNIQUE.
Assign it to A if you like.
Rahel Braun
le 12 Nov 2018
Bruno Luong
le 12 Nov 2018
My problem was that I didn't know how to use unique() properly with 3 groups,
Stephen already answered by just add 'ROWS' argument, to have one identification (third output) by for each 1x3 row (your "groups").
BTW, you might not noticed by using
accumarray(...,data) ./ accumarray(...,1)
is always fater than
accumarray(...,data, ..., @mean)
if speed is matter for you.
Cris LaPierre
le 8 Nov 2018
grpAvg = splitapply(@mean,p,t);
pAvg = grpAvg(t);
[t k p pAvg]
2 commentaires
Cris LaPierre
le 8 Nov 2018
Modifié(e) : Cris LaPierre
le 8 Nov 2018
If your grouping variable is not as clean as it is in this example, you can use the findgroups function to create an index of the unique values in your grouping variable.
Cris LaPierre
le 12 Nov 2018
Using your updated matrix from a comment, here is a robust way to achieve what you want using findgroups and splitapply (assuming variable t,k,l, and p exist and represent the columns of M):
M = [t k l p]
G = findgroups(t,k);
grpAvg = splitapply(@mean,p,G);
pAvg = grpAvg(G);
V = [t k l p pAvg]
The original matrix M is
M =
1.0000 1.0000 1.0000 0.1435
1.0000 1.0000 2.0000 -5.3137
1.0000 2.0000 1.0000 -6.7921
1.0000 2.0000 2.0000 -8.5640
2.0000 1.0000 1.0000 -2.3356
2.0000 1.0000 2.0000 -17.0264
2.0000 2.0000 1.0000 12.6423
2.0000 2.0000 2.0000 8.2006
3.0000 1.0000 1.0000 2.7997
3.0000 1.0000 2.0000 2.6523
3.0000 2.0000 1.0000 -4.9816
3.0000 2.0000 2.0000 13.1869
And resulting matrix V is
V =
1.0000 1.0000 1.0000 0.1435 -2.5851
1.0000 1.0000 2.0000 -5.3137 -2.5851
1.0000 2.0000 1.0000 -6.7921 -7.6780
1.0000 2.0000 2.0000 -8.5640 -7.6780
2.0000 1.0000 1.0000 -2.3356 -9.6810
2.0000 1.0000 2.0000 -17.0264 -9.6810
2.0000 2.0000 1.0000 12.6423 10.4215
2.0000 2.0000 2.0000 8.2006 10.4215
3.0000 1.0000 1.0000 2.7997 2.7260
3.0000 1.0000 2.0000 2.6523 2.7260
3.0000 2.0000 1.0000 -4.9816 4.1026
3.0000 2.0000 2.0000 13.1869 4.1026
Catégories
En savoir plus sur Loops and Conditional Statements dans Centre d'aide et File Exchange
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!