我正在编写一个代码来做一些非常简单的描述性统计,但我发现自己的语法非常重复。 我知道有一种方法可以缩短这些代码,并使用类似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')
关于如何使这项工作的任何想法??
答案 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