在MATLAB中计算平均值进行下采样
假设我有一个包含44100个样本的文件,在fs=44100 Hz的频率下采样。 所以我的文件是1秒长 我想将采样频率降低到8Hz,但我不想通过每44100/8=5512,5个采样并保存在新阵列中来实现。但通过取前5512个样本的平均值,将新数组的1保存到位。然后取样本5513-11024,取其平均值,并保存在新数组的第2个位置。等等取样本11025至11025+5512,将其平均值放在数组的第3处 我知道这一定是某种双倍循环,但我就是不知道如何。。。有什么帮助吗 编辑: 代码,在一个非常手动的方式做什么,我正在寻找 `fs=44100在MATLAB中计算平均值进行下采样,matlab,for-loop,Matlab,For Loop,假设我有一个包含44100个样本的文件,在fs=44100 Hz的频率下采样。 所以我的文件是1秒长 我想将采样频率降低到8Hz,但我不想通过每44100/8=5512,5个采样并保存在新阵列中来实现。但通过取前5512个样本的平均值,将新数组的1保存到位。然后取样本5513-11024,取其平均值,并保存在新数组的第2个位置。等等取样本11025至11025+5512,将其平均值放在数组的第3处 我知道这一定是某种双倍循环,但我就是不知道如何。。。有什么帮助吗 编辑: 代码,在一个非常手动的方
fo=8
A=randn(44100,1);%使用随机数据在fs=44100处采样的阵列
A_resampled = zeros(numel(A)/5512);
first_block = zeros(5512,1);
for i = 1:length(first_block)
first_block(i) = A(i);
end
first_mean_value = mean(first_block);
A_resampled(1) = first_mean_value;
second_block = zeros(5512,1);
for k = 5513:5512+length(second_block)
second_block(k) = A(k);
end
second_mean_value = mean(second_block);
A_resampled(2) = second_mean_value;`
等等
sampling = 1:5512:length(sample);
resampled = zeros(numel(sampling),1);
for ii = 1:length(sampling)-1
resampled(ii,1) = mean(sampling(ii:ii+1));
end
采样
是一个带有索引的数组,用于开始采样,然后循环仅取所有这些位的平均值
采样
是一个带有索引的数组,用于开始采样,然后循环简单地获取所有这些位的平均值。将数组放入2D矩阵,然后沿列查找。为了确保我们可以正确地执行此操作,我们将填充阵列的末端,以确保您的信号是fs/fo
的整数倍,其中fs
是采样频率,fo
是所需频率。。。因此这将分别是44.1khz
和8hz
因此,假设您的信号存储在A
中,请执行以下操作:
%// Defines
A = ....; %// Define your array here
fs = 44100; %// Sampling frequency
fo = 8; %// Desired frequency
%// Determine how many samples there are per chunk
samples_per_chunk = floor(fs/fo);
%// Determine how many total chunks there are
num_chunks = ceil(numel(A)/samples_per_chunk);
%// Create a padded array where it is an integer multiple
%// of the chunk size and insert the original array into this padded
%// array
Apad = zeros(samples_per_chunk*num_chunks,1);
Apad(1:numel(A)) = A;
%// Reshape into 2D matrix
M = reshape(Apad, [], num_chunks);
%// Find average per chunk
out = mean(M, 1);
但是,这样做的结果是,如果数组不是
fs/fo
的整数倍,那么将不必要地平均附加到数组末尾的一组零。如果您不希望发生这种情况,一种方法是创建一个最初填充有NaN
的矩阵,并使用该矩阵,以便NaN
的值都不包含在平均值中。。。从而有效地忽略了填充值
类似这样的方法会起作用:
%// Code as before..
%// ...
%// ...
%// New
Apad = nan(samples_per_chunk*num_chunks,1);
Apad(1:numel(A)) = A;
M = reshape(Apad, [], num_chunks);
out = nanmean(M, 1);
但是,nanmean
需要统计工具箱。如果您没有这个功能,那么您可以自己实现nanmean
。将数组重塑为矩阵M
后,计算每列有多少NaN
元素,然后将所有列相加,除以非NaN
的条目总数,计算平均值
%// Code as before...
%//....
%//....
%// New
M = reshape(Apad, [], num_chunks);
%// Count how total number of NaN values
counts = sum(isnan(M), 1);
%// Set NaN values to zero to not affect mean
M(isnan(M)) = 0;
%// Calculate new average
out = sum(M,2) ./ (size(M,1) - counts);
将数组转换为二维矩阵,然后沿列查找。为了确保我们可以正确地执行此操作,我们将填充阵列的末端,以确保您的信号是fs/fo
的整数倍,其中fs
是采样频率,fo
是所需频率。。。因此这将分别是44.1khz
和8hz
因此,假设您的信号存储在A
中,请执行以下操作:
%// Defines
A = ....; %// Define your array here
fs = 44100; %// Sampling frequency
fo = 8; %// Desired frequency
%// Determine how many samples there are per chunk
samples_per_chunk = floor(fs/fo);
%// Determine how many total chunks there are
num_chunks = ceil(numel(A)/samples_per_chunk);
%// Create a padded array where it is an integer multiple
%// of the chunk size and insert the original array into this padded
%// array
Apad = zeros(samples_per_chunk*num_chunks,1);
Apad(1:numel(A)) = A;
%// Reshape into 2D matrix
M = reshape(Apad, [], num_chunks);
%// Find average per chunk
out = mean(M, 1);
但是,这样做的结果是,如果数组不是
fs/fo
的整数倍,那么将不必要地平均附加到数组末尾的一组零。如果您不希望发生这种情况,一种方法是创建一个最初填充有NaN
的矩阵,并使用该矩阵,以便NaN
的值都不包含在平均值中。。。从而有效地忽略了填充值
类似这样的方法会起作用:
%// Code as before..
%// ...
%// ...
%// New
Apad = nan(samples_per_chunk*num_chunks,1);
Apad(1:numel(A)) = A;
M = reshape(Apad, [], num_chunks);
out = nanmean(M, 1);
但是,nanmean
需要统计工具箱。如果您没有这个功能,那么您可以自己实现nanmean
。将数组重塑为矩阵M
后,计算每列有多少NaN
元素,然后将所有列相加,除以非NaN
的条目总数,计算平均值
%// Code as before...
%//....
%//....
%// New
M = reshape(Apad, [], num_chunks);
%// Count how total number of NaN values
counts = sum(isnan(M), 1);
%// Set NaN values to zero to not affect mean
M(isnan(M)) = 0;
%// Calculate new average
out = sum(M,2) ./ (size(M,1) - counts);
使用如何?让x
表示您的输入向量。然后
n = ceil((1:numel(x))/5512.5); %// blocks of 5512, 5513, 5512, 5513... samples
result = accumarray(n(:), x (:), [], @mean);
请注意,n
自动定义不相等的块大小,最多相差一个样本,以匹配您的分数目标块大小。在您的示例中,块大小是5512
,5513
,5512
,5513
。如何使用?让x
表示您的输入向量。然后
n = ceil((1:numel(x))/5512.5); %// blocks of 5512, 5513, 5512, 5513... samples
result = accumarray(n(:), x (:), [], @mean);
请注意,
n
自动定义不相等的块大小,最多相差一个样本,以匹配您的分数目标块大小。在您的示例中,块大小是5512
,5513
,5512
,5513
。单for循环就足够了。尝试一下,一旦我们看到一些代码单for循环就足够了,我们就会提供帮助。试一试,一旦我们看到一些代码,我们就会提供帮助。你知道Divakar会对你使用循环说些什么吗-P但是OP要求这样做,所以+1感谢回复。但这不符合我的要求。也许我没有很好地解释我自己。我会试着用一种非常手动的方式发布一些代码(在主帖子中)来实现我想要的功能,也许这样会更容易理解。但非常感谢。你知道Divakar会怎么说你使用循环,对吗-P但是OP要求这样做,所以+1感谢回复。但这不符合我的要求。也许我没有很好地解释我自己。我会试着用一种非常手动的方式发布一些代码(在主帖子中)来实现我想要的功能,也许这样会更容易理解。但是非常感谢。@LuisMendo-谢谢:)注意mean
;)中1
的明确用法哦。。。我没有注意到。你能在某个地方加一个“
让它更漂亮吗-D@LuisMendo-:D。。。我可以转置M
并使用2
作为平均值;)我真的不是100%理解代码,但是我得到了第一个551的第一个平均值的正确结果