使用 Matlab 计算两个连续序列中数字的平均值
Average of numbers in two consequetive sequences using Matlab
我有一个包含 13867 X 2 个元素的数组,存储在名为 "data" 的变量中。所以,我想在 Matlab 中执行以下操作:
- 平均值(第 1 行 -> 第 21 行);即取前 21 个元素的平均值
- 平均值(第 22 行 -> 第 43 行);即取接下来 22 个元素的平均值
- 平均值(第 44 行 -> 第 64 行);即取接下来 21 个元素的平均值
- 平均值(第 65 行 -> 第 86 行);即取接下来 22 个元素的平均值
- 重复该过程直到矩阵结束,以便我们取第 13847 行到第 13876 行的最后 21 个元素的平均值。我想要第 1 列和第 2 列中元素的平均值。我不知何故设法在 Excel 中做到了这一点,但这是一个有点麻烦的任务(必须先为行创建索引)。我想最后我们会得到 645 个平均值。
这样做的关键是插入 NaN
行以使较短的块(21 行)与较长的块(22 行)大小相同。这非常简单,使用 Matlab FileExchange:
中的 insertrows
函数
n = 21;
m = 22;
dataPad = insertrows(data, nan(1,size(data,2)), n:(n+m):size(data,1));
之后,第 22 行将是 [NaN, NaN]
,第 66 行将是 [NaN, NaN]
,依此类推。现在计算平均值变得非常容易。简单地重塑这个矩阵,使所有应该被平均的值都在同一列上。最后,使用 nanmean
函数(简单忽略 NaN
的平均函数)得到结果。
我不是 100% 清楚结果应该是 645x2 还是 645x1,即是否也对行进行平均。这将是两种方式对应的 reshape
:
1. 也对行进行平均:
dataPadRearr = reshape(dataPad.',m*size(data,2),[]);
result = nanmean(dataPadRearr,1);
2. 单独保留行:
dataPadRearr = reshape(dataPad,m,[],size(data,2));
result = squeeze(nanmean(dataPadRearr,1));
请注意,在这里,您需要一个最终的 squeeze
,因为 nanmean
的结果将是维度 1x645x2
,这不是很实用。 squeeze
只是删除了这个单例维度。
这是解决它的一种方法,使用 NaNs
、重塑和连接进行填充 -
%// Input
A = rand(13867,2);
%// Two stepsizes
m = 21;
n = 22;
%// Combined stepsize
N = m+n;
%// Pad with NaNs to simplify reshaping & finding averages with nanmean
Apad = cat(1,A,nan(N*ceil(numel(A)/(2*N)) - numel(A)/2,2));
%// Reshape into a 3D array with Combined stepsize number of rows
B = reshape(Apad,N,numel(Apad)/(2*N),[]);
%// Index into first m rows and get nan ignored averages row-wise.
%// Reshape into rows x 2 sized array
C = reshape(cat(1,nanmean(B(1:m,:,:),1),nanmean(B(m+1:end,:,:),1)),[],2);
%// Ignore NaNs and thus have the final output
out = reshape(C(~isnan(C)),[],2);
验证输出
前五行-
>> out(1:4,:)
ans =
0.55694 0.55289
0.49942 0.53502
0.57768 0.40828
0.6347 0.45194
>> mean(A(1:21,:),1)
ans =
0.55694 0.55289
>> mean(A(22:43,:),1)
ans =
0.49942 0.53502
>> mean(A(44:64,:),1)
ans =
0.57768 0.40828
>> mean(A(65:86,:),1)
ans =
0.6347 0.45194
最后一行 -
>> out(end,:)
ans =
0.44631 0.59432
>> mean(A(13847:13867,:),1)
ans =
0.44631 0.59432
借助玩具示例进行解释
使用的样本 -
%// Input
A = rand(17,2)
%// Two stepsizes
m = 3;
n = 4;
1] 输入:
A =
0.64775 0.30635
0.45092 0.50851
0.54701 0.51077
0.29632 0.81763
0.74469 0.79483
0.18896 0.64432
0.68678 0.37861
0.18351 0.81158
0.36848 0.53283
0.62562 0.35073
0.78023 0.939
0.081126 0.87594
0.92939 0.55016
0.77571 0.62248
0.48679 0.58704
0.43586 0.20774
0.44678 0.30125
2] 组合步长:
N =
7
3] 用 NaN 填充的行进行填充,使得行数是 N
-
的倍数
Apad =
0.64775 0.30635
0.45092 0.50851
0.54701 0.51077
0.29632 0.81763
0.74469 0.79483
0.18896 0.64432
0.68678 0.37861
0.18351 0.81158
0.36848 0.53283
0.62562 0.35073
0.78023 0.939
0.081126 0.87594
0.92939 0.55016
0.77571 0.62248
0.48679 0.58704
0.43586 0.20774
0.44678 0.30125
NaN NaN
NaN NaN
NaN NaN
NaN NaN
4] 这部分可能有点棘手。考虑将 Apad
中的每一列制作成一个二维数组,这样我们每列将有 N
个元素,因为这里的目的是在进一步将每一列分成两个子组之后获得每一列的平均值这样的 3D 数组的前三行和其余四行。因此,Apad
有 2 行,我们将有一个包含两个 3D 切片的 3D 数组,这样第一个 3D 切片将是 Apad
中第一列的重塑版本,即 Apad(:,1)
.类似地,第二个 3D 切片对应于 Apad
中的第二列。因此,生成的 3D 数组将是 -
B(:,:,1) =
0.64775 0.18351 0.48679
0.45092 0.36848 0.43586
0.54701 0.62562 0.44678
0.29632 0.78023 NaN
0.74469 0.081126 NaN
0.18896 0.92939 NaN
0.68678 0.77571 NaN
B(:,:,2) =
0.30635 0.81158 0.58704
0.50851 0.53283 0.20774
0.51077 0.35073 0.30125
0.81763 0.939 NaN
0.79483 0.87594 NaN
0.64432 0.55016 NaN
0.37861 0.62248 NaN
5] 沿每列查找 mean/average,其中 nanmean(..,1)
忽略 NaNs
-
>> nanmean(B(1:m,:,:),1)
ans(:,:,1) =
0.54856 0.39254 0.45648
ans(:,:,2) =
0.44188 0.56504 0.36534
>> nanmean(B(m+1:end,:,:),1)
ans(:,:,1) =
0.47919 0.64161 NaN
ans(:,:,2) =
0.65885 0.74689 NaN
6] 将这些平均值连接并重塑为二维数组 -
C =
0.54856 0.44188
0.47919 0.65885
0.39254 0.56504
0.64161 0.74689
0.45648 0.36534
NaN NaN
7] 忽略最终输出的 NaN 行 -
out =
0.54856 0.44188
0.47919 0.65885
0.39254 0.56504
0.64161 0.74689
0.45648 0.36534
我有一个包含 13867 X 2 个元素的数组,存储在名为 "data" 的变量中。所以,我想在 Matlab 中执行以下操作:
- 平均值(第 1 行 -> 第 21 行);即取前 21 个元素的平均值
- 平均值(第 22 行 -> 第 43 行);即取接下来 22 个元素的平均值
- 平均值(第 44 行 -> 第 64 行);即取接下来 21 个元素的平均值
- 平均值(第 65 行 -> 第 86 行);即取接下来 22 个元素的平均值
- 重复该过程直到矩阵结束,以便我们取第 13847 行到第 13876 行的最后 21 个元素的平均值。我想要第 1 列和第 2 列中元素的平均值。我不知何故设法在 Excel 中做到了这一点,但这是一个有点麻烦的任务(必须先为行创建索引)。我想最后我们会得到 645 个平均值。
这样做的关键是插入 NaN
行以使较短的块(21 行)与较长的块(22 行)大小相同。这非常简单,使用 Matlab FileExchange:
insertrows
函数
n = 21;
m = 22;
dataPad = insertrows(data, nan(1,size(data,2)), n:(n+m):size(data,1));
之后,第 22 行将是 [NaN, NaN]
,第 66 行将是 [NaN, NaN]
,依此类推。现在计算平均值变得非常容易。简单地重塑这个矩阵,使所有应该被平均的值都在同一列上。最后,使用 nanmean
函数(简单忽略 NaN
的平均函数)得到结果。
我不是 100% 清楚结果应该是 645x2 还是 645x1,即是否也对行进行平均。这将是两种方式对应的 reshape
:
1. 也对行进行平均:
dataPadRearr = reshape(dataPad.',m*size(data,2),[]);
result = nanmean(dataPadRearr,1);
2. 单独保留行:
dataPadRearr = reshape(dataPad,m,[],size(data,2));
result = squeeze(nanmean(dataPadRearr,1));
请注意,在这里,您需要一个最终的 squeeze
,因为 nanmean
的结果将是维度 1x645x2
,这不是很实用。 squeeze
只是删除了这个单例维度。
这是解决它的一种方法,使用 NaNs
、重塑和连接进行填充 -
%// Input
A = rand(13867,2);
%// Two stepsizes
m = 21;
n = 22;
%// Combined stepsize
N = m+n;
%// Pad with NaNs to simplify reshaping & finding averages with nanmean
Apad = cat(1,A,nan(N*ceil(numel(A)/(2*N)) - numel(A)/2,2));
%// Reshape into a 3D array with Combined stepsize number of rows
B = reshape(Apad,N,numel(Apad)/(2*N),[]);
%// Index into first m rows and get nan ignored averages row-wise.
%// Reshape into rows x 2 sized array
C = reshape(cat(1,nanmean(B(1:m,:,:),1),nanmean(B(m+1:end,:,:),1)),[],2);
%// Ignore NaNs and thus have the final output
out = reshape(C(~isnan(C)),[],2);
验证输出
前五行-
>> out(1:4,:)
ans =
0.55694 0.55289
0.49942 0.53502
0.57768 0.40828
0.6347 0.45194
>> mean(A(1:21,:),1)
ans =
0.55694 0.55289
>> mean(A(22:43,:),1)
ans =
0.49942 0.53502
>> mean(A(44:64,:),1)
ans =
0.57768 0.40828
>> mean(A(65:86,:),1)
ans =
0.6347 0.45194
最后一行 -
>> out(end,:)
ans =
0.44631 0.59432
>> mean(A(13847:13867,:),1)
ans =
0.44631 0.59432
借助玩具示例进行解释
使用的样本 -
%// Input
A = rand(17,2)
%// Two stepsizes
m = 3;
n = 4;
1] 输入:
A =
0.64775 0.30635
0.45092 0.50851
0.54701 0.51077
0.29632 0.81763
0.74469 0.79483
0.18896 0.64432
0.68678 0.37861
0.18351 0.81158
0.36848 0.53283
0.62562 0.35073
0.78023 0.939
0.081126 0.87594
0.92939 0.55016
0.77571 0.62248
0.48679 0.58704
0.43586 0.20774
0.44678 0.30125
2] 组合步长:
N =
7
3] 用 NaN 填充的行进行填充,使得行数是 N
-
Apad =
0.64775 0.30635
0.45092 0.50851
0.54701 0.51077
0.29632 0.81763
0.74469 0.79483
0.18896 0.64432
0.68678 0.37861
0.18351 0.81158
0.36848 0.53283
0.62562 0.35073
0.78023 0.939
0.081126 0.87594
0.92939 0.55016
0.77571 0.62248
0.48679 0.58704
0.43586 0.20774
0.44678 0.30125
NaN NaN
NaN NaN
NaN NaN
NaN NaN
4] 这部分可能有点棘手。考虑将 Apad
中的每一列制作成一个二维数组,这样我们每列将有 N
个元素,因为这里的目的是在进一步将每一列分成两个子组之后获得每一列的平均值这样的 3D 数组的前三行和其余四行。因此,Apad
有 2 行,我们将有一个包含两个 3D 切片的 3D 数组,这样第一个 3D 切片将是 Apad
中第一列的重塑版本,即 Apad(:,1)
.类似地,第二个 3D 切片对应于 Apad
中的第二列。因此,生成的 3D 数组将是 -
B(:,:,1) =
0.64775 0.18351 0.48679
0.45092 0.36848 0.43586
0.54701 0.62562 0.44678
0.29632 0.78023 NaN
0.74469 0.081126 NaN
0.18896 0.92939 NaN
0.68678 0.77571 NaN
B(:,:,2) =
0.30635 0.81158 0.58704
0.50851 0.53283 0.20774
0.51077 0.35073 0.30125
0.81763 0.939 NaN
0.79483 0.87594 NaN
0.64432 0.55016 NaN
0.37861 0.62248 NaN
5] 沿每列查找 mean/average,其中 nanmean(..,1)
忽略 NaNs
-
>> nanmean(B(1:m,:,:),1)
ans(:,:,1) =
0.54856 0.39254 0.45648
ans(:,:,2) =
0.44188 0.56504 0.36534
>> nanmean(B(m+1:end,:,:),1)
ans(:,:,1) =
0.47919 0.64161 NaN
ans(:,:,2) =
0.65885 0.74689 NaN
6] 将这些平均值连接并重塑为二维数组 -
C =
0.54856 0.44188
0.47919 0.65885
0.39254 0.56504
0.64161 0.74689
0.45648 0.36534
NaN NaN
7] 忽略最终输出的 NaN 行 -
out =
0.54856 0.44188
0.47919 0.65885
0.39254 0.56504
0.64161 0.74689
0.45648 0.36534