我有以下数据:
A = [1 2 ; 3 2; 4 7; 10 2; 6 7; 10 9]
B = [1 2 3; 4 4 9; 1 8 0; 3 7 9; 3 6 8]
C = [4; 10; 6; 3; 1]
A =
1 2
3 2
4 7
10 2
6 7
10 9
B =
1 2 3
4 4 9
1 8 0
3 7 9
3 6 8
C.' =
4 10 6 3 1
对于A(:,2)
中的每个唯一值,我需要在A(:,1)
中取相应的值,
在C
中查找其值,然后获取B
中的相关行并计算其均值。
结果应为length(unique(A(:,2))
x size(B,2)
;
此示例的预期结果:
B
的第2,4和5行的平均值
说明:与A
中的值“2”对应的索引1,3和10是
在C
的指数2,4,5中。相应地:
B
的第1行和第3行的平均值。B
的第2行的平均值。我现在通过在unique
上应用A
并迭代每个值,搜索正确的索引来计算它。我的数据集很大,所以需要很长时间。我该如何避免循环?
答案 0 :(得分:6)
让我们一步一步地做你在问题中说的话:
对于 A(:, 2)
中的每个唯一值:
[U, ia, iu] = unique(A(:, 2));
获取 A(:, 1)
中的相应值,并在 C
中查找其值:
[tf, loc] = ismember(A(:, 1), C);
为了以防万一,我们还建议确保在C
中实际找到所有值:
assert(all(tf))
然后获取 B
中的相关行并计算其均值:
[X, Y] = meshgrid(1:size(B, 2), iu);
result = accumarray([Y(:), X(:)], reshape(B(loc, :), 1, []), [], @mean);
希望这有帮助! :)
%// Sample input
A = [1 2 ; 3 2; 4 7; 10 2; 6 7; 10 9];
B = [1 2 3; 4 4 9; 1 8 0; 3 7 9; 3 6 8];
C = [4; 10; 6; 3; 1];
%// Compute means
[U, ia, iu] = unique(A(:, 2));
[tf, loc] = ismember(A(:, 1), C);
[X, Y] = meshgrid(1:size(B, 2), iu);
result = accumarray([Y(:), X(:)], reshape(B(loc, :), [], 1), [], @mean);
结果是:
result =
3.3333 5.6667 8.6667
1.0000 5.0000 1.5000
4.0000 4.0000 9.0000
答案 1 :(得分:3)
这是另一种没有arrayfun
和accumarray
使用良好的旧式矩阵乘法的解决方案:
r = bsxfun(@eq, A(:,1), C')*(1:numel(C))';
[~,m,n] = unique(A(:,2));
f=histc(n, 1:numel(m));
result = diag(1./f)*bsxfun(@eq, 1:numel(m), n).'*B(r,:);
我对其他两个解决方案进行了基准测试,看起来比两者都要快。重复1000次:
以下是基准代码:
N = 1e3;
tic
for k=1:N,
r = bsxfun(@eq, A(:,1), C')*(1:numel(C))'; % faster than [~,r] = ismember(A(:,1), C)
[~,m,n] = unique(A(:,2));
f=histc(n, 1:numel(m));
result2 = diag(1./f)*bsxfun(@eq, 1:numel(m), n).'*B(r,:);
end
toc
tic
for k=1:N,
[U, ia, iu] = unique(A(:, 2));
[tf, loc] = ismember(A(:, 1), C);
[X, Y] = meshgrid(1:size(B, 2), iu);
result1 = accumarray([Y(:), X(:)], reshape(B(loc, :), [], 1), [], @mean);
end
toc
tic
for k=1:N,
D = [arrayfun(@(x) find(C == x,1,'first'), A(:,1) ), A(:,2)];
data = [B(D(:,1),:), D(:,2)];
st = grpstats(data(:,1:3),data(:,4:4),{'mean'});
end
toc
答案 2 :(得分:1)
谢谢, 我还想到了:
D = [arrayfun(@(x) find(C == x,1,'first'), A(:,1) ), A(:,2)];
data = [B(D(:,1),:), D(:,2)];
st = grpstats(data(:,1:3),data(:,4:4),{'mean'});