我有一个21128x9细胞的细胞阵列,按第1列排序,例如(大规模简化):
A=[1 3; 1 5; 1 3; 2 1; 2 2; 2 3; 3 5; 3 5]
A =
1 3
1 5
1 3
2 1
2 2
2 3
3 5
3 5
其中第1列中的某些值比其他值重复。
我想要做的是获取第一列的每个值的第二列的平均值,但仅针对前两个值。
即
ans= 1 4
2 1.5
3 5
我正在尝试使用这个基本功能
means = accumarray(A(:,1) ,A(:,2),[],@mean);
但我不知道如何让它只适用于每组的前两个值。我假设我需要一个 for 循环,类似于:
for ;
means = accumarray(A(:,1) ,A(:,2),[],@mean);
end
我不知道 需要什么。
答案 0 :(得分:4)
accumarray
将一个向量传递给匿名函数,所以你可以这样做,例如:
A = [1 3; 1 5; 1 3; 2 1; 2 2; 2 3; 3 5; 3 5];
maxAvgs = 3;
accumarray(A(:, 1), A(:, 2), [], @(x)mean(x(1:min(length(x), maxAvgs))))
ans =
3.6667
2.0000
5.0000
maxAvgs = 2;
accumarray(A(:, 1), A(:, 2), [], @(x)mean(x(1:min(length(x), maxAvgs))))
ans =
4.0000
1.5000
5.0000
每当您不确定涉及匿名函数的情况时,您可以将您的匿名函数编写为@(varargin)disp(varargin)
;这将显示输入参数。在这种情况下,这不起作用,因为accumarray
需要您传递的函数返回一个参数。但是,您仍然可以将其设置为匿名函数并从脚本运行代码;在编辑器窗口的行上设置一个断点,确保为断点的位置选择“匿名函数”。
修改强>
在我的实际数据中,有些有60个值,有些有120个,有些有180个。 作为补充,是否有可能然后运行平均函数 下一批价值(即价值61-120,然后是121-180)?
要在评论中执行您的建议,我建议您创建一个函数splitMean
并将其传递给accumarray
:
function y = splitMean(x, n)
% If length of x doesn't divide by n, the extra elements will be averaged
% separately
extra = mod(length(x), n);
M = length(x)-extra;
meanData = reshape(x(1:M), M / n, n);
extraMean = [];
if extra > 0, extraMean = mean(x(M+1:end)); end
if ~isempty(meanData)
y = {[mean(meanData).'; extraMean]};
else
y = {extraMean};
end
然后,
maxAvgs = 2;
cell2mat(accumarray(A(:, 1), A(:, 2), [], @(x)splitMean(x, maxAvgs)))
ans =
4.0000
3.0000
1.5000
3.0000
5.0000
%%% Without the cell2mat:
ans =
[2x1 double]
[2x1 double]
[ 5]
通过这种方式,您可以获得每个组可以同时提供的所有方法集。请注意cell2mat
。如果您希望它们按组索引拆分,则删除它,您将获得一个单元格数组。