【问题标题】:Average of numbers in two consequetive sequences using Matlab使用 Matlab 对两个连续序列中的数字进行平均
【发布时间】:2015-12-15 15:15:02
【问题描述】:

我有一个包含 13867 X 2 个元素的数组,并存储在名为“data”的变量中。因此,我想在 Matlab 中执行以下操作:

  • 平均(第 1 行 -> 第 21 行);即取前 21 个元素的平均值
  • 平均(第 22 行 -> 第 43 行);即取接下来 22 个元素的平均值
  • 平均(第 44 行 -> 第 64 行);即取接下来 21 个元素的平均值
  • 平均(第 65 行 -> 第 86 行);即取接下来 22 个元素的平均值
  • 重复该过程直到矩阵结束,以便我们取第 13847 行到第 13876 行的最后 21 个元素的平均值。我想要第 1 列和第 2 列中元素的平均值。我以某种方式设法在 Excel 中执行此操作,但这是一项繁琐的任务(必须先为行创建索引)。我猜最后我们会得到 645 个平均值。

【问题讨论】:

  • 读完这个问题后我的思考过程: 1. 想出使用循环的明显方法。 2. 尝试弄清楚我如何对其进行矢量化(如果它们都是 21 或 22 个元素,那将非常简单)。 3. 2分钟后放弃,因为我猜有人会想出一个聪明的矢量化方法来做到这一点,把我的循环答案留给 rot =P
  • 就目前而言,这是一个非常简单的问题,您尝试过什么?

标签: matlab sequence average rows skip


【解决方案1】:

这样做的关键是插入NaN 行以使较短的块(21 行)与较长的块(22 行)大小相同。这很简单,使用来自Matlab FileExchangeinsertrows 函数:

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 只是删除了这个单一维度。

【讨论】:

  • 代码没有产生我期望的结果,我希望result 的前两个元素等于mean(data(1:21,:))
  • @Daniel 我自己也不是 100% 确定这一点。在问题中,Emma 说她预计平均数为 645,所以我采用了这种方式。唯一改变的是reshape,所以我在答案中添加了两种方式。
  • @hbaderts 您的解决方案也很有效。使用的方法简单、灵巧。谢谢!
  • @hbaderts 哦,结果应该是一个 645x2 的数组。亲爱的你为这两种方式提供答案:)
【解决方案2】:

这是解决问题的一种方法,使用 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] 使用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

【讨论】:

  • 非常感谢您的解决方案和及时响应。你让我开心!它完美地工作我是Matlab的新手,所以你能更详细地解释一下代码的作用吗? :)
  • @Emma 查看编辑是否有助于理解解决方案。第四步是重要且可能有点令人困惑的步骤,因此请多加注意。很高兴让你开心! :)
  • 非常感谢您花时间和精力来解释解决方案。你们存在真是太好了!
  • 您好,好久不见!我再次遇到了一些平均问题,但现在更普遍了。在我在这里提出的问题中,我事先知道数据是如何格式化的,但是如果数据有点不统一,那就真的很麻烦了。你能检查一下这个问题,看看这个过程是否可以自动化吗? stackoverflow.com/questions/36598096/…谢谢你们!
  • @Emma 确实有一段时间了!在那里发表评论,试试看:)
猜你喜欢
  • 1970-01-01
  • 2023-03-10
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-08-19
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多