Matlab使用for循环中的数组循环函数

时间:2015-09-06 21:48:58

标签: matlab loops for-loop cell

我正在编写一个代码来做一些非常简单的描述性统计,但我发现自己的语法非常重复。 我知道有一种方法可以缩短这些代码,并使用类似for循环的东西使其更加优雅和节省时间,但我还不太热衷于编码(还)知道如何做到这一点... < / p>

我有三个变量或组(所有数据,条件1和条件2)。我还有8个matlab函数,我需要在三组中的每一组上执行(例如,均值,中位数)。我将所有数据保存在一个表中,其中每列对应于一个函数(例如均值),每一行是在相应组上执行的函数(例如(1,1)是&#39;所有数据& #39;,(2,1)是&#39; cond 1&#39;的意思,(3,1)是&#39; cond 2&#39;的意思。当我输出到我可以在excel中打开的csv文件时,保留此结构很重要。这些列再次根据函数进行标记,行按1)所有数据2)cond 1和3)cond 2排序。

顺便说一下,我正在使用的数据位于这些矩阵的第二列。

所以这是我实现这一目标的繁琐方式:

x = cell(3,8);

x{1,1} = mean(alldata(:,2)); 
x{2,1} = mean(cond1data(:,2)); 
x{3,1} = mean(cond2data(:,2)); 

x{1,2} = median(alldata(:,2));
x{2,2} = median(cond1data(:,2));
x{3,2} = median(cond2data(:,2));

x{1,3} = std(alldata(:,2));
x{2,3} = std(cond1data(:,2));
x{3,3} = std(cond2data(:,2));

x{1,4} = var(alldata(:,2));   % variance
x{2,4} = var(cond1data(:,2));
x{3,4} = var(cond2data(:,2));

x{1,5} = range(alldata(:,2));
x{2,5} = range(cond1data(:,2));
x{3,5} = range(cond2data(:,2));

x{1,6} = iqr(alldata(:,2));  % inter quartile range
x{2,6} = iqr(cond1data(:,2));
x{3,6} = iqr(cond2data(:,2));

x{1,7} = skewness(alldata(:,2));
x{2,7} = skewness(cond1data(:,2));
x{3,7} = skewness(cond2data(:,2));

x{1,8} = kurtosis(alldata(:,2));
x{2,8} = kurtosis(cond1data(:,2));
x{3,8} = kurtosis(cond2data(:,2));

%  write output to .csv file using cell to table conversion

T = cell2table(x, 'VariableNames',{'mean', 'median', 'stddev', 'variance', 'range', 'IQR', 'skewness', 'kurtosis'});
writetable(T,'descriptivestats.csv')

我知道有一种方法可以循环使用这些东西,并在更短的代码中获得相同的输出。我试着写一个for循环,但我只是困惑自己,不知道如何做到这一点。无论如何我都会把它包括在内,所以也许你可以知道我想要做什么。

x = cell(3,8);
data = [alldata, cond2data, cond2data];
dfunction = ['mean', 'median', 'std', 'var', 'range', 'iqr', 'skewness', 'kurtosis'];
for i = 1:8, 
    for y = 1:3
        x{y,i} = dfucntion(i)(data(1)(:,2));
        x{y+1,i} = dfunction(i)(data(2)(:,2));
        x{y+2,i} = dfunction(i)(data(3)(:,2));
    end
end


T = cell2table(x, 'VariableNames',{'mean', 'median', 'stddev', 'variance', 'range', 'IQR', 'skewness', 'kurtosis'});
writetable(T,'descriptivestats.csv')

关于如何使这项工作的任何想法??

2 个答案:

答案 0 :(得分:2)

您想要使用函数句柄的单元格数组。最简单的方法是使用@运算符,如

dfunctions = {@mean, @median, @std, @var, @range, @iqr, @skewness, @kurtosis};

此外,您希望将三个数据变量合并为一个变量,以便更轻松地对它们进行迭代。我可以看到两种选择。如果您的数据变量在维度上都是M-by-2,则可以将它们连接成M-by-2-by-3三维数组。你可以用

做到这一点
data = cat(3, alldata, cond1data, cond2data);

将索引表达式转换为检索所需值的数据data(:, 2, y)。也就是说,我认为这种方法必须复制大量数据,而且可能不是性能最佳的。将数据组合在一起的另一种方法是采用1乘3的单元阵列,如下所示:

data = {alldata, cond1data, cond2data};

将索引表达式转换为在这种情况下检索所需值的数据data{y}(:, 2)

由于您从y == 1循环到y == 3,因此在内循环体中只需要一行,而不是三行。

for y = 1:3
    x{y, i} = dfunctions{i}(data{y}(:,2));
end

最后,要获取包含函数名称的字符串的单元格数组以传递给cell2table,可以使用cellfun将func2str应用于dfunctions的每个元素:

funcnames = cellfun(@func2str, dfunctions, 'UniformOutput', false);

最终版本如下:

dfunctions = {@mean, @median, @std, @var, @range, @iqr, @skewness, @kurtosis};
data = {alldata, cond1data, cond2data};
x = cell(length(data), length(dfunctions));
for i = 1:length(dfunctions)
    for y = 1:length(data)
        x{y, i} = dfunctions{i}(data{y}(:,2));
    end
end

funcnames = cellfun(@func2str, dfunctions, 'UniformOutput', false);
T = cell2table(x, 'VariableNames', funcnames);
writetable(T,'descriptivestats.csv');

答案 1 :(得分:1)

您可以使用str2func

创建函数的单元格数组
function_string = {'mean', 'median', 'std', 'var', 'range', 'iqr', 'skewness', 'kurtosis'};
dfunction = {};
for ii = 1:length(function_string)
    fun{ii} = str2func(function_string{ii})
end

然后您可以根据需要在数据上使用它:

for ii = 1:8, 
    for y = 1:3
        x{y,i} = dfucntion{ii}(data(1)(:,2));
        x{y+1,i} = dfunction{ii}(data(2)(:,2));
        x{y+2,i} = dfunction{ii}(data(3)(:,2));
    end
end