【问题标题】:MATLAB: Get mean of first n values sorted by first columnMATLAB:获取按第一列排序的前 n 个值的平均值
【发布时间】:2013-04-12 20:28:14
【问题描述】:

我有一个按第 1 列排序的 21128x9 单元格数组,例如(大量简化):

    A=[1 3; 1 5; 1 3; 2 1; 2 2; 2 3; 3 5; 3 5]

    A =

         1     3
         1     5
         1     3
         2     1
         2     2
         2     3
         3     5
         3     5

第 1 列中的某些值比其他值重复更多。

我想要做的是为第一列的每个值获取第二列的平均值,但仅针对前两个值。

    ans= 1 4
         2 1.5
         3 5

我正在尝试使用这个基本功能

    means = accumarray(A(:,1) ,A(:,2),[],@mean);

但我不确定如何让它仅适用于每个组的前两个值。我假设我需要一个 for 循环,类似于:

    for ;
        means = accumarray(A(:,1) ,A(:,2),[],@mean);
    end

我不知道 for 需要什么。

【问题讨论】:

    标签: matlab mean


    【解决方案1】:

    accumarray 将向量传递给匿名函数,因此您可以这样做,例如:

    A = [1 3; 1 5; 1 3; 2 1; 2 2; 2 3; 3 5; 3 5];
    maxAvgs = 3;
    accumarray(A(:, 1), A(:, 2), [], @(x)mean(x(1:min(length(x), maxAvgs))))
    
    ans =
    
    3.6667
    2.0000
    5.0000
    
    maxAvgs = 2;
    accumarray(A(:, 1), A(:, 2), [], @(x)mean(x(1:min(length(x), maxAvgs))))
    
    ans =
    
    4.0000
    1.5000
    5.0000
    

    当您在涉及匿名函数的情况下不确定时,您可以将匿名函数写为@(varargin)disp(varargin);这将显示输入参数。在这种情况下,这不起作用,因为accumarray 要求您传递给它的函数返回一个参数。但是,您仍然可以将其设置为匿名函数并从脚本运行您的代码;在编辑器窗口的行上设置断点,确保为断点的位置选择“匿名函数”。

    编辑:

    在我的实际数据中,有些有 60 个值,有些有 120,有些有 180。 另外,是否可以在 下一批值(即值 61-120,然后是 121-180)?

    按照您在评论中的要求,我建议创建一个函数splitMean 并将其传递给accumarray

    function y = splitMean(x, n)
    % If length of x doesn't divide by n, the extra elements will be averaged
    % separately
    extra = mod(length(x), n);
    M = length(x)-extra;
    
    meanData = reshape(x(1:M), M / n, n);
    
    extraMean = [];
    if extra > 0, extraMean = mean(x(M+1:end)); end
    if ~isempty(meanData)
        y = {[mean(meanData).'; extraMean]};
    else
        y = {extraMean};
    end
    

    那么,

    maxAvgs = 2;
    cell2mat(accumarray(A(:, 1), A(:, 2), [], @(x)splitMean(x, maxAvgs)))
    
    ans =
    
    4.0000
    3.0000
    1.5000
    3.0000
    5.0000
    
    %%% Without the cell2mat:
    
    ans =
    
    [2x1 double]
    [2x1 double]
    [         5]
    

    通过这种方式,您可以获得每个组可以同时提供的所有方法。注意cell2mat。如果您希望它们按组索引拆分,则将其删除,您将获得一个元胞数组。

    【讨论】:

    • 啊!先生,您是一位学者,一位绅士!看起来很简单,但我想我还没有完全掌握 MATLAB 语法。
    • 在我的实际数据中,有些有 60 个值,有些有 120,有些有 180。此外,是否可以对下一批值(即值 61- 120,然后是 121-180)?
    • 太棒了,谢谢!你是明星!
    猜你喜欢
    • 1970-01-01
    • 2015-02-04
    • 2013-11-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-05-28
    • 2015-10-19
    相关资源
    最近更新 更多