【问题标题】:When and why should I use cellfun in Matlab?我何时以及为什么应该在 Matlab 中使用 cellfun?
【发布时间】:2013-05-10 13:01:09
【问题描述】:

我对 MATLAB 中的 cellfun 函数有疑问。

什么时候/为什么应该使用它,什么时候可以放弃它?

一个简单的例子:假设我有一个单元格a,我想找到a 中所有值的平均值。

a{1} = [1 2;3 4];
a{2} = [1 2 3;4 5 6; 7 8 9];

我的方法是这样的:

mean([a{1}(:); a{2}(:)])

合适的cellfun 版本会是什么,会更好吗?

我试过做这样的事情,(显然不工作):

mean_a = mean(cellfun(@mean, a,'UniformOutput',0))

谢谢!

【问题讨论】:

标签: matlab cell


【解决方案1】:

cellfun 就像循环遍历单元矩阵和
在每个单元格上分别执行指定的功能。
它通常比明确地做同样的事情要快
在循环中,但基本的区别是它很容易
写和读 - 它立即清楚调用是什么
正在做。但你也可以自己编写循环。

在您的具体情况下,您可以这样使用cellfun

mean_a = mean(cellfun(@(x) mean(x(:)), a));

如果您有数千个单元格并且想要做某事
对于他们每个人,您要么使用循环,要么使用cellfun
BTW:@(x) 表示你想要每个单元格的内容
被理解为x 这样mean(x(:)) 给你什么
你想要 - 单元格的整个矩阵内容的平均值。

【讨论】:

    【解决方案2】:

    这当然取决于你想做什么。 cellfun 旨在单独作用于单元阵列中的每个单元。如果您想获取单元格数组值的全局平均值,并坚持使用cellfun,那么这应该可以:

    mean_a = mean(cell2mat(cellfun(@mean, a,'UniformOutput',0)))
    

    【讨论】:

      【解决方案3】:

      根据您尝试的解决方案,我想给出的答案将解决您的问题。但是,在我看来,您的解决方案会比其他解决方案更重视某些价值,并且可能并非对所有读者都有价值。
      使用你的矩阵,

      mean([a{1}(:); a{2}(:)]) ~= mean([mean(a{1}(:)) mean(a{2}(:))])
                        4.2308 ~= 3.75
      

      这是 numel(a{1}) ~= numel(a{2}) 的情况。

      接受的解决方案等价于上述等式的右侧,但原始实现(显然)等于左侧。考虑到您的需要,任何一个都可能是正确的。

      为了平衡,我提供了一种(多种)方法来实现单元格所有元素的非加权平均值,方法是将每个矩阵重塑为列数组并将它们连接起来:

      b = cellfun(@(x) reshape(x, 1, []), a, 'UniformOutput', false);
      mean_a = mean([b{:}])
      

      【讨论】:

      • 欢迎来到 SO!请编辑答案,以便清楚您在谈论什么尝试的解决方案/答案。它们的显示顺序并不总是相同的。一旦您的答案位于其他答案之间,读者就会想知道您在说什么。 (我不能对您或其他人回答的内容发表任何声明)
      【解决方案4】:

      我喜欢使用 cellfun 来绘制操作而不是循环,例如,如果我有多组传感器数据并且每组有多个列(因为每组有多个传感器),使用起来非常方便

      numOfSensors = 5;
      numOfSets = 6;
      
      %% sample data preparation
      x = 1:100;
      y = rand(length(x), numOfSets*numOfSensors);
      yCell = mat2cell(y, 100, numOfSensors*ones(1,numOfSets)); % this is my sensor data
      scaleCell = num2cell(fliplr(cumsum(1:numOfSets)));
      yCell = cellfun(@(x, scale)x.*scale, yCell, scaleCell, 'unif', false);
      
      %% plot preparation
      nameCell = arrayfun(@(x)['sensor set ' num2str(x)], 1:numOfSets, 'unif', false);
      colorCell = num2cell(lines(numOfSets), 2)';
      
      %% plot
      figure, hold all,
      set(gca, 'ColorOrder', [0 0 0], 'LineStyleOrder', {'-','--','-*','-.',':'})
      h = cellfun(@(y, name, c)plot(x, y, 'linewidth', 1.5, 'displayName', name, 'color', c), yCell, nameCell, colorCell, 'unif', false);
      hh = cellfun(@(x)x(1), h, 'unif', false);
      legend([hh{:}])
      

      而不是循环。此示例绘制所有数据集,每个数据集以自己的颜色绘制,每个数据集的每个传感器使用其他线型。图例仅针对每个数据集显示(注意:这也可以通过使用 hggroups 来完成)。

      或者一个更简单的用例 - 我又有一个数据元胞数组,想简要了解一下:

      figure, hold all, cellfun(@plot,dataCell)
      

      就是这样,一行,在命令行中非常快。

      另一个很好的用例是使用 mean()、max()、min()、std() 等压缩高维数据数值数据,但您已经提到过这一点。如果数据大小不一致,这一点就变得更加重要。

      【讨论】:

        猜你喜欢
        • 2014-05-22
        • 2011-06-07
        • 1970-01-01
        • 2010-12-07
        • 1970-01-01
        • 2018-11-12
        • 2015-08-24
        • 2013-11-21
        • 2023-03-08
        相关资源
        最近更新 更多