【问题标题】:average number of different values in a column一列中不同值的平均数
【发布时间】:2013-06-17 10:38:20
【问题描述】:

我在 Matlab 中有一个问题。就是这样,我尝试对一列中不同数量的值取平均值。例如,如果我们有下面的列,

X = [1 1 2 3 4 3 8 2 1 3 5 6 7 7 5]

首先,我想先取 5 个值的平均值并绘制它们。在上述情况下,我应该收到三个可以绘制的平均值。然后一次取10个值,以此类推。 我想知道您是否必须编写自定义代码来修复它。

【问题讨论】:

  • X:看起来像一行,但那是一列!
  • 如果是一维的,那没关系。

标签: matlab average


【解决方案1】:

最快的方法可能是将初始向量 X 重新排列到某个矩阵中,每列存储所需的平均值:

A = reshape(X, N, []);

其中N 是新矩阵中所需的行数,空括号 ([]) 告诉 MATLAB 自动计算列数。然后您可以使用mean 对每一列进行平均:

X_avg = mean(A);

向量X_avg 存储结果。这可以像这样在一行中完成:

X_avg = mean(reshape(X, N, []));

注意X 中的元素数量必须能被N 整除,否则您必须先填充它(例如 用零),或者处理“剩余" 尾元素分开:

tail = mod(numel(X), N);
X_avg = mean(reshape(X(1:numel(X) - tail), N, [])); %// Compute average values
X_avg(end + 1) = mean(X(end - tail + 1:end));       %// Handle leftover elements

稍后您可以将此代码放入循环中,计算并绘制每次迭代中N 的不同值的平均值。

示例 #1

X = [1 1 2 3 4 3 8 2 1 3 5 6 7 7 5];
N = 5;

tail = mod(numel(X), N);
X_avg = mean(reshape(X(1:numel(X) - tail), N, []))
X_avg(end + 1) = mean(X(end - tail + 1:end))

结果是:

X_avg =
    2.2000   3.4000   6.0000

示例 #2

这是另一个例子(这次X的长度不能被N整除):

X = [1 1 2 3 4 3 8 2 1 3 5 6 7 7 5];
N = 10;

tail = mod(numel(X), N);
X_avg = mean(reshape(X(1:numel(X) - tail), N, []))
X_avg(end + 1) = mean(X(end - tail + 1:end))

结果是:

X_avg =
    2.8000   6.0000

【讨论】:

  • +1,很好的解决方案。我不完全确定 OP 想要什么,但我想在计算平均值时不包括最后一列中的零会更有意义......
  • @RobertP。如果X 中的元素数量不是N 的倍数,那将是有问题的。但是,如果 OP 不希望在计算中包含填充的零,则可以使用 mean(X(end - mod(numel(X), N) + 1:end)) 单独重新计算最后一个平均值
  • @EitanT:我知道使用reshape 会有问题,这就是为什么我没有提出解决方案=P
  • @RobertP。我已经编辑了问题以在平均最后一个元素时忽略零,而 X 的长度不是 N 的倍数。
  • @RobertP。看起来不错,除了它需要统计工具箱:)
【解决方案2】:

这应该可以解决问题:

对于选定的N(您要取平均值的值的数量):

N = 5;
mean_vals = arrayfun(@(n) mean(X(n-1+(1:N))),1:N:length(X))

注意:这不会检查Index exceeds matrix dimensions

如果您想跳过最后一个数字,这应该可以:

mean_vals = arrayfun(@(n) mean(X(n-1+(1:N))),1:N:(length(X)-mod(length(X),N)));

添加剩余值:

if mod(length(X),N) ~= 0
   mean_vals(end+1) = mean(X(numel(X)+1-mod(length(X),N):end))
end

更新:这是对Eitan's 第一个答案的修改(在编辑之前)。它使用nanmean(),它取所有不是NaN 的值的平均值。因此,不要用zeros 填充剩余的行,而是用NaN 填充它们,然后取平均值。

X = [X(:); NaN(mod(N - numel(X), N), 1)];
X_avg = nanmean(reshape(X, N, []));

【讨论】:

  • 感谢您的快速回复。我运行了您的代码,但遇到了您说我可以得到的问题,索引超出矩阵尺寸。 @(n) mean (X(n-1 + (1: N))) 中的错误我尝试了其他值,例如 2,并且它起作用了。我的列包含 390 个值。我想使用 N = 10、N = 20、N = 30 和 N = 50。所以我的问题是是否可以针对我提到的 N 进行修复?
  • 它可以修复,是的。但这取决于当条件:mod(length(X),N) == 0; 不满足时您想要做什么(N=20N = 50 就是这种情况)。您想跳过最后 40 个数字吗?假设您想要N=3,并取X = [1 2 3 4] 的平均值。你打算用 4 做什么?
  • 如果我理解正确,那么我可以跳过导致问题的值,使N = 10、20、30、50个函数。
  • 我不确定你想说什么。你想跳过最后的数字吗? (这将是我之前评论中的数字 4),还是您想跳过导致问题的 N?在我的评论中是 N=3 吗?在您的情况下,只有 N=10 和 N=30 有效。
  • 好的,只有 10 和 30 个作品。我试图说我想跳过导致问题的值,或者只是对剩余的值取平均值,N 不再影响。
【解决方案3】:

如果您发布一些代码并准确指出什么不起作用,将会很有帮助。

作为第一个指针。如果

X = [1 1 2 3 4 3 8 2 1 3 5 6 7 7 5]

您感兴趣的 5 块中的三种方法是

mean(X(1:5))
mean(X(6:10))
mean(X(11:15))

你必须想出一个 for 循环或者其他方法来遍历索引。

【讨论】:

    【解决方案4】:

    我想你想要这样的东西(我有一段时间没有使用 Matlab,我希望语法是正确的):

    X = [1 1 2 3 4 3 8 2 1 3 5 6 7 7 5],
    currentAmount=5,
    block=0,
    while(numel(X)<=currentAmount)
      while(numel(X)<=currentAmount+block*currentAmount)
        mean(X(block*currentAmount+1:block*currentAmount+currentAmount));
        block =block+1;
      end;
      currentAmount = currentAmount+5;
      block=0;
    end
    

    此代码将首先循环遍历所有元素,一次计算 5 个元素的平均值。然后,它将扩展到 10 个元素。然后到 15,依此类推,直到要从中求均值的元素数大于列中的元素数。

    【讨论】:

    • 您需要将平均值存储在变量中。在您的情况下,它需要是一个单元格或结构,因为它的长度会有所不同(取决于currentAmount)。
    • @RobertP。感谢您的输入,我认为他可能只想绘制变量。
    【解决方案5】:

    如果您希望在 N 维向量中平均 K 随机样本,那么您可以使用:

    N = length(X);
    K = 20;    % or 10, or 30, or any integer less than or equal to N
    indices = randperm(N, K);    % gives you K random indices from the range 1:N
    result = mean(X(indices));   % averages the values of X at the K random 
                                 % indices from above
    

    更紧凑的形式是:

    K = 20;
    result = mean(X(randperm(length(X), K)));
    

    如果您只是想从列表中获取每个K 连续样本并对它们进行平均,那么我相信前面的答案之一会给您想要的。

    【讨论】:

      【解决方案6】:

      如果您经常需要执行此操作,可能值得为它编写自己的函数。我建议使用@EitanT 的基本思想:填充数据、重塑、取每一列的平均值。但是,我建议不要在末尾包含零填充数字,而是分别取“散乱”数据点的平均值:

      function m = meanOfN(x, N)
      % function m = meanOfN(x, N)
      % create groups of N elements of vector x
      % and return their mean
      % if numel(x) is not a multiple of N, the last value returned
      % will be for fewer than N elements
      Nf = N * floor( numel( x ) / N ); % largest multiple of N <= length of x
      xr = reshape( x( 1:Nf ), N, []);
      m = mean(xr);
      if Nf < N
        m = [m mean( x( Nf + 1:end ) )];
      end
      

      此函数将准确返回您所要求的内容:在 N=5 的 15 元素向量的情况下,它返回 3 个值。当输入向量的大小不是 N 的倍数时,最后返回的值将是“剩余的平均值”。

      当您需要取一组数字的平均值时,通常会感兴趣的是“运行平均值”。因此,您可能想要,而不是获得[mean(x(1:5)) mean(x(6:10)) mean(11:15))]

      m(1) = mean(x(1:N));
      m(2) = mean(x(2:N+1));
      m(3) = mean(x(3:N+2));
      ...etc
      

      这可以通过将数据与向量进行简单卷积来实现;为了完整起见,这里有一种可能的编码方式:

      function m = meansOfN(x, n)
      % function m = meansOfN(x, n)
      % taking the running mean of the values in x
      % over n samples. Returns a row vector of size (sizeof(x) - n + 1)
      % if numel(x) < n, this returns an empty matrix
      mv = ones(N,1) / N; % vector of ones, normalized
      m = convn(x(:), mv, 'valid'); % perform 1D convolution
      

      在您的路径中使用这两个函数(将它们分别保存在一个名为meanOfN.mmeansOfN.m 的文件中),您可以做任何您想做的事情。在任何程序中您都可以编写

      myMeans = meanOfN(1:30, 5);
      myMeans2 = meansOfN(1:30, 6);
      

      等等。 Matlab 会找到函数,执行计算,返回结果。为这样的特定操作编写自定义函数非常有帮助 - 它不仅可以保持代码整洁,而且您只需测试一次函数...

      【讨论】:

        猜你喜欢
        • 2016-08-01
        • 1970-01-01
        • 2019-03-20
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2018-11-20
        相关资源
        最近更新 更多