可能有一个更有效的解决方案,但一种方法是使用 sum 来查找给定列中的非零行数 . 然后通过使用 arrayfun 循环遍历所有列并在列中的零之前平均 N 行来获取A的平均值 .
%// Number of elements to average
N = 3;
%// Last non-zero row in each column
lastrow = sum(A ~= 0, 1);
%// Ensure that we don't have any indices less than 1
startrow = max(lastrow - N + 1, 1);
%// Compute the mean for each column using the specified rows
means = arrayfun(@(k)mean(A(startrow(k):lastrow(k),k)), 1:size(A, 2));
在下面的示例中,我执行此操作,然后仅返回我们关心的区域的值(其中平均值仅由每列中的最后 N 非零组成)
%// Find the last non-zero entry in each column
lastrow = sum(A ~= 0, 1);
%// Use convolution to compute the mean for every N rows
%// This will be applied to ALL of A
convmean = conv2(A, ones(N, 1)./N);
%// Select only the means that we care about
%// Because of the padding of CONV2, these will live at the rows
%// stored in LASTROW
means = convmean(sub2ind(size(convmean), lastrow, 1:size(A, 2)));
%// Now correct for cases where fewer than N samples were averaged
means = (means * N) ./ min(lastrow, N);
而输出又是一样的
3.0000 3.0000 2.0000 2.0000 2.0000 3.0000 3.6667
比较
我运行了一个快速测试脚本来比较这两种方法之间的性能 . 很明显,基于卷积的方法要快得多 .
这是完整的测试脚本 .
function benchmark()
dims = round(linspace(1, 1000, 100));
times1 = zeros(size(dims));
times2 = zeros(size(dims));
N = 3;
for k = 1:numel(dims)
A = triu(rand(dims(k)));
times1(k) = timeit(@()test_arrayfun(N, A));
A = triu(rand(dims(k)));
times2(k) = timeit(@()test_convolution(N, A));
end
figure;
plot(dims, times1);
hold on
plot(dims, times2);
legend({'arrayfun', 'convolution'})
xlabel('Dimension of A')
ylabel('Execution Time (seconds)')
end
function test_arrayfun(N, A)
%// Last non-zero row in each column
lastrow = sum(A ~= 0, 1);
%// Ensure that we don't have any indices less than 1
startrow = max(lastrow - N + 1, 1);
%// Compute the mean for each column using the specified rows
means = arrayfun(@(k)mean(A(startrow(k):lastrow(k),k)), 1:size(A, 2));
end
function test_convolution(N, A)
%// Find the last non-zero entry in each column
lastrow = sum(A ~= 0, 1);
%// Use convolution to compute the mean for every N rows
%// This will be applied to ALL of A
convmean = conv2(A, ones(N, 1)./N);
%// Select only the means that we care about
%// Because of the padding of CONV2, these will live at the rows
%// stored in LASTROW
means = convmean(sub2ind(size(convmean), lastrow, 1:size(A, 2)));
%// Now correct for cases where fewer than N samples were averaged
means = (means * N) ./ min(lastrow, N);
end
1 回答
可能有一个更有效的解决方案,但一种方法是使用
sum
来查找给定列中的非零行数 . 然后通过使用arrayfun
循环遍历所有列并在列中的零之前平均N
行来获取A的平均值 .Example
对于您的示例数据,这将产生:
更新:替代方案
另一种方法是使用卷积来实际为您解决此问题 . 您可以使用卷积内核计算均值 . 如果你想要矩阵的所有3行组合的平均值,你的内核将是:
当与感兴趣的矩阵卷积时,这将计算输入矩阵内所有3行组合的平均值 .
在下面的示例中,我执行此操作,然后仅返回我们关心的区域的值(其中平均值仅由每列中的最后
N
非零组成)而输出又是一样的
比较
我运行了一个快速测试脚本来比较这两种方法之间的性能 . 很明显,基于卷积的方法要快得多 .
这是完整的测试脚本 .