我有一个352x11矩阵,由第1列索引,有10个数据点。一些索引值重复出现。我想找到重复的指数并计算重复试验的平均数据点(如果可能的话,避免循环)。
例如,
x =
26 77.5700 17.9735 32.7200
27 40.5887 16.6100 31.5800
28 60.4734 18.5397 33.6200
28 35.6484 27.2000 54.8000
29 95.3448 19.0000 37.7300
30 82.7273 30.4394 39.1400
最终:
ans =
26 77.5700 17.9735 32.7200
27 40.5887 16.6100 31.5800
28 48.0609 22.8699 44.2150
29 95.3448 19.0000 37.7300
30 82.7273 30.4394 39.1400
我在想是否使用
J = find(diff(x(:,1))==0);
找到重复值的位置,然后我可以将函数应用到x
的相应位置,但是我从哪里开始?
答案 0 :(得分:6)
更通用的方法是使用unique
来查找唯一索引值:
[U, ix, iu] = unique(x(:, 1));
然后accumarray
:
[c, r] = meshgrid(1:size(x, 2), iu);
y = accumarray([r(:), c(:)], x(:), [], @mean);
要处理的输入值实际上是accumarray
的 second 参数。
accumarray
的第一个参数是一个矩阵,每一行是(累积的)输出矩阵中的一组索引,它对应于来自匹配行的一个值。作为第二个参数给出的矢量。
将输出视为单元阵列。第二个参数是输入值,第一个参数中的每一行告诉输出矩阵accumarray
的哪个单元应该存储相应的输入值。输出“单元格数组”完成后,函数(在我们的例子中为mean
)将应用于每个单元格。
以下是一个较小矩阵的简短示例:
x = [27, 10, 8;
28, 20, 10;
28, 30, 50];
我们通过以下方式找到唯一值:
[U, ix, iu] = unique(x(:, 1));
向量U
存储唯一值,iu
表示与每行关联的值的哪个索引(请注意,此解决方案中我们没有使用ix
)。在我们的例子中,我们得到了:
U =
27
28
iu =
1
2
2
现在我们应用accumarray
:
[c, r] = meshgrid(1:size(x, 2), iu);
y = accumarray([r(:), c(:)], x(:), [], @mean);
meshgrid
和[r(:), c(:)]
的奇特技巧会产生一组索引:
[r(:), c(:)] =
1 1
2 1
2 1
1 2
2 2
2 2
1 3
2 3
2 3
这些是输入值x(:)
的索引,它是x
的列向量等价物:
x(:) =
27
28
28
10
20
30
8
10
50
积累过程:
看看刚刚发生了什么?两个值28都累积在同一个单元格中(最终它们将被平均)。这个过程继续:
依旧......
一旦所有值都存储在单元格中,函数mean
就会应用于每个单元格,我们得到最终的输出矩阵:
y =
27 10 8
28 25 30
答案 1 :(得分:4)
您可以将accumarray
应用于多个列as shown here
labels = x(:,1) - min(x(:, 1)) + 1;
labels = [repmat(labels(:),size(x,2),1), kron(1:size(x,2),ones(1,numel(labels))).'];
totals = accumarray(labels,x(:),[], @mean);
这是根据Gnovice's代码改编的。
要使代码适用于您的代码,您需要删除前面的所有零
totals(find(mean((totals == zeros(size(totals)))')), :) = [];
产生所需的
26.0000 77.5700 17.9735 32.7200
27.0000 40.5887 16.6100 31.5800
28.0000 48.0609 22.8699 44.2100
29.0000 95.3448 19.0000 37.7300
30.0000 82.7273 30.4394 39.1400
答案 2 :(得分:0)
您可能会发现accumarray
@mean
有用:
假设第一列保留某些1 .. k
的值k <= size(x,1)
,您可以使用
col = accumarray( x(:,1), x(:,2), [], @mean ); % second column
答案 3 :(得分:0)
给你输入
x = [ ...
26 77.5700 17.9735 32.7200; ...
27 40.5887 16.6100 31.5800; ...
28 60.4734 18.5397 33.6200; ...
28 35.6484 27.2000 54.8000; ...
29 95.3448 19.0000 37.7300; ...
30 82.7273 30.4394 39.1400];
您可以使用unique
的第三个输出创建一个索引数组,其中重复的vgalue共享相同的索引。
%Get index of unique values (1 - N)
[~, ~, ix] = unique(x(:,1))
然后您可以使用此数组重建矩阵,将重复值与您选择的功能相结合。
%Use accumarry to rebuild the matrix one column at a time
result = [...
accumarray( ix, x(:,1), [], @max ) ... %Many functions works here, as all inputs are the same. E.G. @mean, @max, @min
accumarray( ix, x(:,2), [], @mean ) ... %Use mean to combine data, per problem statement.
accumarray( ix, x(:,3), [], @mean ) ...
accumarray( ix, x(:,4), [], @mean ) ...
]