[英]How to determine the mean of the last e.g. 100 non-zero numbers in each column of a matrix in matlab
我想在matlab中計算矩陣每列中最后三個非零數的平均值。 在末尾用列填充列以創建相同長度的向量。
示例矩陣:
A = [5 6 3 5 6 8 9;
1 2 3 5 4 7 6;
0 1 2 3 4 5 6;
0 0 1 2 3 4 5;
0 0 0 1 2 3 4;
0 0 0 0 2 3 4;
0 0 0 0 2 3 4;
0 0 0 0 0 0 3]
可能有一個更有效的解決方案,但一種方法是使用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));
例
對於您的示例數據,這將產生:
3.0000 3.0000 2.0000 2.0000 2.0000 3.0000 3.6667
另一種方法是使用卷積來實際為您解決此問題。 您可以使用卷積內核計算均值。 如果你想要矩陣的所有3行組合的平均值,你的內核將是:
kernel = [1; 1; 1] ./ 3;
當與感興趣的矩陣卷積時,這將計算輸入矩陣內所有3行組合的平均值。
B = [1 2 3;
4 5 6;
7 8 9];
conv2(B, kernel)
0.3333 0.6667 1.0000
1.6667 2.3333 3.0000
4.0000 5.0000 6.0000
3.6667 4.3333 5.0000
2.3333 2.6667 3.0000
在下面的示例中,我執行此操作,然后僅返回我們關心的區域的值(其中平均值僅由每列中的最后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
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.