【问题标题】:Alternative to splitapply in Matlab在 Matlab 中替代 splitapply
【发布时间】:2018-04-02 05:54:53
【问题描述】:

我正在尝试运行使用 splitapply function 的其他人的 Matlab 代码,该代码仅在 R2018a 中可用。我目前正在使用 R2015a;是否有一个简单(尽管效率较低)的替代实现可以实现(暂时)使用的相同目的?

【问题讨论】:

    标签: matlab split-apply-combine


    【解决方案1】:

    记录在案的splitapply 用法也依赖于findgroups。这两个都在 R2015b[1] 中实现。

    您可以使用unique 的第三个输出代替findgroups,并使用一个简单的循环代替splitapply。这是一个假设 data 是列向量的示例,您可以轻松地将其调整为适用于矩阵数据。

    % With splitapply
    g = findgroups( data );           
    m = splitapply( @mean, data, g ); % Your function in place of mean here
    
    % Without splitapply (pre-R2015b)
    [~, ~, g] = unique( data ); % Get group indices
    m = zeros(max(g), 1);       % Initialise the output matrix
    for ii = 1:max(g)
        m(ii) = mean( data( g == ii ) ); % Your function in place of mean here
    end 
    

    通过一些快速测试,我发现这些方法在合理大小的数组上的速度相当。对于 data 中的 ~100 个组和 ~1e6 个元素,我发现循环方法慢了 4 倍,但仍然相当快。


    [1] 注意:MathWorks 文档默认为最新版本,这就是您认为splitapply 是在 R2018a 中引入的原因。但是,在每个函数的文档页面的底部,都会说明它是何时引入的。对于splitapply,我们看到“Introduced in R2015b”。

    【讨论】:

      【解决方案2】:

      其实splitapply已经在R2015b中引入了。

      splitapply 文档中描述的任何方法,函数 combines two steps in the Split-Apply-Combine Workflow

      下图(来自splitapply在线文档描述过程:

      基本上splitapply使用函数findgroups对输入数据进行分组,然后对每组数据应用一个函数。

      不幸的是,findgroups 也已在 R2015b 中引入,因此主要问题是找到实现它的方法。

      实现findgroups 的“通用”版本可能需要大量时间才能使其能够处理多种不同类型的数据集。

      您可以开始以与您必须使用的特定数据集匹配的形式开始实施它。

      基本上,您可以使用unique 函数实现它的简化版本。

      这个想法是使用它来检索:

      • 数据集中唯一条目的列表:这些将是
      • 数据集中对应于这些组的条目索引

      获得数据集中组的索引后,您可以使用它们来下选数据集的值,并将它们用作您需要应用的函数的输入。

      您可以在下面找到一个可能的实现示例,该示例重现了splitapply 的在线帮助中提供的示例。

      当然,这不是使用“每个”数据集的“通用”实现,实际上它适用于示例的特定输入,但我希望它可以作为一个起点。

      splitapply的在线示例

      Excerpt of the on-line documentation

      load patients
      meanBMIFcn = @(h,w)mean((w ./ (h.^2)) * 703);
      DT = table(Height,Weight);
      GT = table(Gender,Smoker);
      [G,results] = findgroups(GT);
      meanBMI = splitapply(meanBMIFcn,DT,G);
      results.meanBMI = meanBMI
      

      输出

      results=4×3 table
           Gender     Smoker    meanBMI
          ________    ______    _______
      
          'Female'    false     21.672 
          'Female'    true      21.669 
          'Male'      false     26.578 
          'Male'      true      26.458 
      

      一种可能的实现方式

      clear w
      
      % Find the unique entries in the first dataset
      [uni_list_1,~,uni_idx_1]=unique(Gender)
      n_group_1=length(uni_list_1)
      
      % Find the unique entries in the second dataset
      [uni_list_2,~,uni_idx_2]=unique(Smoker)
      n_group_2=length(uni_list_2)
      
      % Get the indices of the occurrencies of the combinatin of the two
      % entities
      for g1=1:length(uni_list_1)
         for g2=1:length(uni_list_2)
            data_set.(uni_list_1{g1}).(['cond_' num2str(uni_list_2(g2))])=(uni_idx_1 == g1) & (uni_idx_2 == g2)
         end
      end
      
      % Define the function to be applied
      meanBMIFcn = @(h,w)mean((w ./ (h.^2)) * 703);
      
      % Extract the data matching the desired conditions and use them as input to
      % the disired function
      for g1=1:length(uni_list_1)
         for g2=1:length(uni_list_2)
            height=Height(data_set.(uni_list_1{g1}).(['cond_' num2str(uni_list_2(g2))]));
            weight=Weight(data_set.(uni_list_1{g1}).(['cond_' num2str(uni_list_2(g2))]));
            result.data_set.(uni_list_1{g1}).(['cond_' num2str(uni_list_2(g2))])=meanBMIFcn(height,weight)
         end
      end
      

      输出

      输出是结构体形式,其字段是组和附加条件

      >> result
      result = 
          data_set: [1x1 struct]
      >> result.data_set
      ans = 
          Female: [1x1 struct]
            Male: [1x1 struct]
      >> result.data_set.Female
      ans = 
          cond_0: 21.6721
          cond_1: 21.6686
      >> result.data_set.Male
      ans = 
          cond_0: 26.5775
          cond_1: 26.4584
      

      【讨论】:

      • 嗨 il_raffa。我是这里的一名志愿编辑,编辑有时会做的一件事就是为了简洁而删减帖子。我注意到你已经 111 次希望你的贡献有所帮助,但这可以被认为是理所当然的,因为没有人希望他们的工作没有帮助。另一种选择是网站上的数百万个答案可以附加这个字符串,但由于这将是多余的,我们说没有它们网站会更好。我们在签名方面也是如此,事实上我认为帮助中心特别要求人们不要在他们的帖子上签名。
      • 因此,如果您以后可以避免添加这些东西,那就太好了——它会稍微减少志愿者的工作量,他们已经有很多工作要做。谢谢。
      【解决方案3】:

      您可以从 statistics 工具箱中查看grpstats

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2018-04-18
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2012-06-29
        • 1970-01-01
        相关资源
        最近更新 更多